Merge branches 'acpi-scan', 'acpi-tad', 'acpi-extlog' and 'acpi-misc'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 25 Aug 2023 18:49:52 +0000 (20:49 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 25 Aug 2023 18:49:52 +0000 (20:49 +0200)
Merge ACPI device enumeration changes, ACPI TAD and extlog drivers
updates, and miscellaneous ACPI-related changes for 6.6-rc1:

 - Defer enumeration of devices with _DEP pointing to IVSC (Wentong Wu).

 - Install SystemCMOS address space handler for ACPI000E (TAD) to meet
   platform firmware expectations on some platforms (Zhang Rui).

 - Fix finding the generic error data in the ACPi extlog driver for
   compatibility with old and new firmware interface versions (Xiaochun
   Lee).

 - Remove assorted unused declarations of functions (Yue Haibing).

 - Move AMBA bus scan handling into arm64 specific directory (Sudeep
   Holla).

* acpi-scan:
  ACPI: scan: Defer enumeration of devices with a _DEP pointing to IVSC device

* acpi-tad:
  ACPI: TAD: Install SystemCMOS address space handler for ACPI000E

* acpi-extlog:
  ACPI: extlog: Fix finding the generic error data for v3 structure

* acpi-misc:
  ACPI: Remove assorted unused declarations of functions
  ACPI: Remove unused extern declaration acpi_paddr_to_node()
  ACPI: Move AMBA bus scan handling into arm64 specific directory

869 files changed:
.mailmap
Documentation/ABI/testing/sysfs-bus-cxl
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/ABI/testing/sysfs-platform-hidma
Documentation/ABI/testing/sysfs-platform-hidma-mgmt
Documentation/admin-guide/hw-vuln/gather_data_sampling.rst [new file with mode: 0644]
Documentation/admin-guide/hw-vuln/index.rst
Documentation/admin-guide/hw-vuln/srso.rst [new file with mode: 0644]
Documentation/admin-guide/kdump/vmcoreinfo.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml
Documentation/devicetree/bindings/net/mediatek,net.yaml
Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml
Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
Documentation/filesystems/locking.rst
Documentation/filesystems/porting.rst
Documentation/i2c/writing-clients.rst
Documentation/networking/nf_conntrack-sysctl.rst
MAINTAINERS
Makefile
arch/alpha/include/asm/processor.h
arch/alpha/kernel/setup.c
arch/arm/boot/dts/arm/integratorap.dts
arch/arm/boot/dts/microchip/sam9x60.dtsi
arch/arm/boot/dts/nspire/nspire.dtsi
arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts
arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira.dtsi
arch/arm/boot/dts/nxp/imx/imx6sll.dtsi
arch/arm/boot/dts/nxp/imx/imx6sx.dtsi
arch/arm/boot/dts/nxp/imx/imx7s.dtsi
arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi
arch/arm/mach-pxa/sharpsl_pm.h
arch/arm/mach-pxa/spitz_pm.c
arch/arm/mach-zynq/pm.c
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
arch/arm64/boot/dts/arm/vexpress-v2m-rs1.dtsi [deleted symlink]
arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-rdk.dts
arch/arm64/boot/dts/freescale/imx8mm-phycore-som.dtsi
arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
arch/arm64/boot/dts/freescale/imx8mm.dtsi
arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi
arch/arm64/boot/dts/freescale/imx8mn.dtsi
arch/arm64/boot/dts/freescale/imx8mq.dtsi
arch/arm64/boot/dts/freescale/imx93.dtsi
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
arch/arm64/boot/dts/qcom/sa8775p-ride.dts
arch/arm64/boot/dts/qcom/sc7180.dtsi
arch/arm64/boot/dts/qcom/sc8180x.dtsi
arch/arm64/boot/dts/qcom/sm8150.dtsi
arch/arm64/boot/dts/qcom/sm8250.dtsi
arch/arm64/boot/dts/qcom/sm8350.dtsi
arch/arm64/boot/dts/renesas/r9a07g044.dtsi
arch/arm64/boot/dts/renesas/r9a07g054.dtsi
arch/arm64/boot/dts/rockchip/px30.dtsi
arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts
arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts
arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts
arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts
arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi
arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts
arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi
arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts
arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts
arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts
arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3-io.dts
arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi
arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts
arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dtsi
arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi
arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
arch/arm64/include/asm/el2_setup.h
arch/arm64/include/asm/fpsimd.h
arch/arm64/include/asm/kvm_asm.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/processor.h
arch/arm64/include/uapi/asm/bitsperlong.h [new file with mode: 0644]
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/signal.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/hyp/nvhe/ffa.c
arch/arm64/kvm/hyp/nvhe/switch.c
arch/ia64/include/asm/acpi.h
arch/ia64/include/asm/processor.h
arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
arch/parisc/Kconfig.debug
arch/parisc/boot/compressed/misc.c
arch/parisc/include/asm/dma.h
arch/parisc/include/asm/ftrace.h
arch/parisc/include/asm/spinlock.h
arch/parisc/include/asm/spinlock_types.h
arch/parisc/kernel/entry.S
arch/parisc/kernel/firmware.c
arch/parisc/kernel/ftrace.c
arch/parisc/kernel/parisc_ksyms.c
arch/parisc/kernel/pci-dma.c
arch/parisc/kernel/pdt.c
arch/parisc/kernel/perf.c
arch/parisc/kernel/processor.c
arch/parisc/kernel/setup.c
arch/parisc/kernel/signal.c
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/unaligned.c
arch/parisc/lib/ucmpdi2.c
arch/parisc/mm/fault.c
arch/parisc/mm/fixmap.c
arch/parisc/mm/init.c
arch/parisc/mm/ioremap.c
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/word-at-a-time.h
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/rtas_flash.c
arch/powerpc/kernel/trace/ftrace_mprofile.S
arch/powerpc/mm/init_64.c
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/powermac/time.c
arch/riscv/Kconfig
arch/riscv/include/asm/acpi.h
arch/riscv/include/asm/cacheflush.h
arch/riscv/include/asm/insn.h
arch/riscv/include/asm/mmio.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/asm/vmalloc.h
arch/riscv/include/uapi/asm/bitsperlong.h [new file with mode: 0644]
arch/riscv/kernel/acpi.c
arch/riscv/kernel/compat_vdso/Makefile
arch/riscv/kernel/cpu.c
arch/riscv/kernel/crash_core.c
arch/riscv/kernel/elf_kexec.c
arch/riscv/kernel/irq.c
arch/riscv/kernel/smp.c
arch/riscv/kernel/traps.c
arch/riscv/lib/uaccess.S
arch/riscv/mm/init.c
arch/riscv/mm/kasan_init.c
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/include/uapi/asm/ptrace.h
arch/s390/kernel/sthyi.c
arch/s390/kvm/intercept.c
arch/s390/mm/vmem.c
arch/sparc/include/asm/processor_64.h
arch/x86/Kconfig
arch/x86/boot/compressed/idt_64.c
arch/x86/boot/compressed/sev.c
arch/x86/entry/vdso/vma.c
arch/x86/hyperv/hv_apic.c
arch/x86/hyperv/hv_init.c
arch/x86/hyperv/hv_vtl.c
arch/x86/hyperv/ivm.c
arch/x86/hyperv/mmu.c
arch/x86/hyperv/nested.c
arch/x86/include/asm/acpi.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/entry-common.h
arch/x86/include/asm/linkage.h
arch/x86/include/asm/mshyperv.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/segment.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/alternative.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cpu.h
arch/x86/kernel/kprobes/opt.c
arch/x86/kernel/static_call.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/kvm/cpuid.c
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/svm.h
arch/x86/kvm/svm/vmenter.S
arch/x86/kvm/x86.c
arch/x86/lib/retpoline.S
arch/x86/xen/enlighten_pv.c
block/blk-cgroup.c
block/blk-core.c
block/blk-crypto-fallback.c
block/blk-iocost.c
block/blk-mq.c
block/elevator.c
block/fops.c
crypto/af_alg.c
drivers/accel/ivpu/ivpu_gem.c
drivers/accel/qaic/qaic_control.c
drivers/accel/qaic/qaic_data.c
drivers/acpi/ac.c
drivers/acpi/acpi_cmos_rtc.c
drivers/acpi/acpi_extlog.c
drivers/acpi/acpi_processor.c
drivers/acpi/acpi_tad.c
drivers/acpi/acpi_video.c
drivers/acpi/acpica/acdebug.h
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acpredef.h
drivers/acpi/acpica/dbcmds.c
drivers/acpi/acpica/dbinput.c
drivers/acpi/acpica/dswstate.c
drivers/acpi/acpica/exserial.c
drivers/acpi/acpica/psopcode.c
drivers/acpi/acpica/utdebug.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/hed.c
drivers/acpi/internal.h
drivers/acpi/nfit/core.c
drivers/acpi/processor_core.c
drivers/acpi/processor_pdc.c
drivers/acpi/resource.c
drivers/acpi/scan.c
drivers/acpi/thermal.c
drivers/acpi/video_detect.c
drivers/acpi/x86/utils.c
drivers/android/binder.c
drivers/android/binder_alloc.c
drivers/android/binder_alloc.h
drivers/ata/libata-scsi.c
drivers/base/cpu.c
drivers/block/rbd.c
drivers/block/rnbd/rnbd-clt-sysfs.c
drivers/block/zram/zram_drv.c
drivers/bus/ti-sysc.c
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm_crb.c
drivers/char/tpm/tpm_tis.c
drivers/clk/Kconfig
drivers/clk/imx/clk-imx93.c
drivers/clk/mediatek/clk-mt8183.c
drivers/clk/meson/clk-pll.c
drivers/counter/Kconfig
drivers/cpufreq/amd-pstate.c
drivers/cpuidle/cpuidle-psci-domain.c
drivers/cpuidle/dt_idle_genpd.c
drivers/cpuidle/dt_idle_genpd.h
drivers/crypto/caam/ctrl.c
drivers/cxl/core/mbox.c
drivers/cxl/core/memdev.c
drivers/cxl/cxlmem.h
drivers/dma/Kconfig
drivers/dma/idxd/device.c
drivers/dma/mcf-edma.c
drivers/dma/owl-dma.c
drivers/dma/pl330.c
drivers/dma/xilinx/xdma.c
drivers/firmware/arm_scmi/mailbox.c
drivers/firmware/arm_scmi/raw_mode.c
drivers/firmware/arm_scmi/smc.c
drivers/firmware/smccc/soc_id.c
drivers/gpio/gpio-sim.c
drivers/gpio/gpio-ws16c48.c
drivers/gpio/gpiolib-sysfs.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/amdkfd/kfd_device.c
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
drivers/gpu/drm/bridge/ite-it6505.c
drivers/gpu/drm/bridge/lontium-lt9611.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_gem_shmem_helper.c
drivers/gpu/drm/i915/display/intel_display_device.c
drivers/gpu/drm/i915/display/intel_sdvo.c
drivers/gpu/drm/i915/gt/gen8_engine_cs.c
drivers/gpu/drm/i915/gt/gen8_engine_cs.h
drivers/gpu/drm/i915/gt/intel_gpu_commands.h
drivers/gpu/drm/i915/gt/intel_gt_regs.h
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
drivers/gpu/drm/i915/gvt/edid.c
drivers/gpu/drm/i915/i915_active.c
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_dumb.c
drivers/gpu/drm/qxl/qxl_gem.c
drivers/gpu/drm/qxl/qxl_ioctl.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/hv/connection.c
drivers/hv/hv_balloon.c
drivers/hv/hv_common.c
drivers/hwmon/aquacomputer_d5next.c
drivers/hwmon/pmbus/bel-pfe.c
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/busses/i2c-designware-master.c
drivers/i2c/busses/i2c-hisi.c
drivers/i2c/busses/i2c-imx-lpi2c.c
drivers/i2c/busses/i2c-sun6i-p2wi.c
drivers/i2c/busses/i2c-tegra.c
drivers/iio/adc/ad7192.c
drivers/iio/adc/ina2xx-adc.c
drivers/iio/adc/meson_saradc.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
drivers/iio/frequency/admv1013.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
drivers/iio/industrialio-core.c
drivers/iio/light/rohm-bu27008.c
drivers/iio/light/rohm-bu27034.c
drivers/infiniband/core/umem.c
drivers/infiniband/hw/bnxt_re/main.c
drivers/infiniband/hw/bnxt_re/qplib_res.c
drivers/infiniband/hw/hfi1/chip.c
drivers/interconnect/qcom/bcm-voter.c
drivers/interconnect/qcom/icc-rpmh.h
drivers/interconnect/qcom/sa8775p.c
drivers/interconnect/qcom/sm8450.c
drivers/interconnect/qcom/sm8550.c
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/isdn/mISDN/dsp.h
drivers/isdn/mISDN/dsp_cmx.c
drivers/isdn/mISDN/dsp_core.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
drivers/media/platform/nxp/imx7-media-csi.c
drivers/media/platform/qcom/venus/hfi_cmds.c
drivers/media/usb/uvc/uvc_v4l2.c
drivers/memory/tegra/mc.c
drivers/memory/tegra/tegra194.c
drivers/memory/tegra/tegra234.c
drivers/misc/cardreader/rts5227.c
drivers/misc/cardreader/rts5228.c
drivers/misc/cardreader/rts5249.c
drivers/misc/cardreader/rts5260.c
drivers/misc/cardreader/rts5261.c
drivers/misc/cardreader/rtsx_pcr.c
drivers/misc/tps6594-esm.c
drivers/mmc/core/block.c
drivers/mmc/host/moxart-mmc.c
drivers/mmc/host/sdhci_f_sdh30.c
drivers/mmc/host/sunplus-mmc.c
drivers/mmc/host/wbsd.c
drivers/mtd/nand/raw/fsl_upm.c
drivers/mtd/nand/raw/meson_nand.c
drivers/mtd/nand/raw/omap_elm.c
drivers/mtd/nand/raw/rockchip-nand-controller.c
drivers/mtd/nand/spi/toshiba.c
drivers/mtd/nand/spi/winbond.c
drivers/mtd/spi-nor/spansion.c
drivers/net/bonding/bond_main.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/ocelot/felix.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/freescale/enetc/enetc_pf.c
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/i40e/i40e_nvm.c
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_fdir.c
drivers/net/ethernet/intel/iavf/iavf_fdir.h
drivers/net/ethernet/intel/ice/ice_eswitch.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/igc/igc.h
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/korina.c
drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
drivers/net/ethernet/marvell/octeon_ep/octep_main.c
drivers/net/ethernet/marvell/prestera/prestera_pci.c
drivers/net/ethernet/marvell/prestera/prestera_router.c
drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c
drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlx5/core/sriov.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
drivers/net/ethernet/microsoft/mana/mana_en.c
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/qlogic/qed/qed_dev_api.h
drivers/net/ethernet/qlogic/qed/qed_fcoe.c
drivers/net/ethernet/qlogic/qed/qed_fcoe.h
drivers/net/ethernet/qlogic/qed/qed_hw.c
drivers/net/ethernet/qlogic/qed/qed_iscsi.c
drivers/net/ethernet/qlogic/qed/qed_iscsi.h
drivers/net/ethernet/qlogic/qed/qed_l2.c
drivers/net/ethernet/qlogic/qed/qed_l2.h
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/sfc/ef100_nic.c
drivers/net/ethernet/sfc/falcon/selftest.c
drivers/net/ethernet/sfc/selftest.c
drivers/net/ethernet/sfc/siena/selftest.c
drivers/net/ethernet/sfc/tc.c
drivers/net/ethernet/socionext/netsec.c
drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/macsec.c
drivers/net/pcs/pcs-rzn1-miic.c
drivers/net/phy/at803x.c
drivers/net/phy/broadcom.c
drivers/net/phy/phy_device.c
drivers/net/tap.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/lan78xx.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/zaurus.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/net/vxlan/vxlan_vnifilter.c
drivers/net/wireguard/allowedips.c
drivers/net/wireguard/selftest/allowedips.c
drivers/net/wireless/ath/ath11k/ahb.c
drivers/net/wireless/ath/ath11k/pcic.c
drivers/net/wireless/ath/ath12k/wmi.c
drivers/net/wireless/ath/ath6kl/Makefile
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
drivers/net/wireless/legacy/rayctl.h
drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
drivers/net/wireless/realtek/rtw89/mac.c
drivers/net/xen-netback/netback.c
drivers/nvme/host/core.c
drivers/nvme/host/ioctl.c
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/of/dynamic.c
drivers/of/kexec.c
drivers/of/platform.c
drivers/of/unittest.c
drivers/parisc/sba_iommu.c
drivers/parport/parport_gsc.c
drivers/parport/parport_gsc.h
drivers/pci/bus.c
drivers/pci/controller/Kconfig
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/dwc/pcie-designware.c
drivers/pci/controller/dwc/pcie-designware.h
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/of.c
drivers/pinctrl/qcom/pinctrl-msm.c
drivers/pinctrl/qcom/pinctrl-msm.h
drivers/pinctrl/qcom/pinctrl-sa8775p.c
drivers/platform/mellanox/mlxbf-tmfifo.c
drivers/platform/x86/amd/pmf/sps.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel/speed_select_if/isst_if_common.c
drivers/platform/x86/lenovo-ymc.c
drivers/platform/x86/mlx-platform.c
drivers/platform/x86/msi-ec.c
drivers/platform/x86/serial-multi-instantiate.c
drivers/powercap/intel_rapl_common.c
drivers/powercap/intel_rapl_msr.c
drivers/powercap/intel_rapl_tpmi.c
drivers/regulator/da9063-regulator.c
drivers/regulator/qcom-rpmh-regulator.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/scsi/zfcp_fc.c
drivers/scsi/53c700.c
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_scsi.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/qedf/qedf_main.c
drivers/scsi/qedi/qedi_main.c
drivers/scsi/raid_class.c
drivers/scsi/scsi_proc.c
drivers/scsi/sd.c
drivers/scsi/snic/snic_disc.c
drivers/scsi/storvsc_drv.c
drivers/soc/aspeed/aspeed-socinfo.c
drivers/soc/aspeed/aspeed-uart-routing.c
drivers/soc/imx/imx8mp-blk-ctrl.c
drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_core.h
drivers/thermal/thermal_trip.c
drivers/thunderbolt/tb.c
drivers/thunderbolt/tmu.c
drivers/tty/Kconfig
drivers/tty/n_gsm.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/serial_base.h
drivers/tty/serial/serial_base_bus.c
drivers/ufs/host/ufs-renesas.c
drivers/usb/common/usb-conn-gpio.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/udc/core.c
drivers/usb/storage/alauda.c
drivers/usb/typec/altmodes/displayport.c
drivers/usb/typec/mux/Kconfig
drivers/usb/typec/mux/nb7vpq904m.c
drivers/usb/typec/tcpm/tcpm.c
drivers/vdpa/mlx5/core/mlx5_vdpa.h
drivers/vdpa/mlx5/core/mr.c
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/vdpa/pds/Makefile
drivers/vdpa/pds/debugfs.c
drivers/vdpa/pds/vdpa_dev.c
drivers/vdpa/pds/vdpa_dev.h
drivers/vdpa/vdpa.c
drivers/vdpa/vdpa_user/vduse_dev.c
drivers/vhost/scsi.c
drivers/video/fbdev/amifb.c
drivers/video/fbdev/atmel_lcdfb.c
drivers/video/fbdev/goldfishfb.c
drivers/video/fbdev/mmp/hw/mmp_ctrl.c
drivers/video/fbdev/ssd1307fb.c
drivers/virtio/virtio_mem.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_pci_legacy.c
drivers/virtio/virtio_vdpa.c
fs/btrfs/block-group.c
fs/btrfs/block-group.h
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/delayed-inode.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_map.c
fs/btrfs/inode.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/tree-checker.c
fs/btrfs/volumes.c
fs/ceph/dir.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.c
fs/coda/dir.c
fs/erofs/super.c
fs/erofs/zdata.c
fs/exfat/balloc.c
fs/exfat/dir.c
fs/exportfs/expfs.c
fs/file.c
fs/gfs2/file.c
fs/gfs2/trans.c
fs/inode.c
fs/jfs/namei.c
fs/nfs/direct.c
fs/nfs/nfs42proc.c
fs/nfs/nfs4proc.c
fs/nfs/sysfs.c
fs/nfsd/vfs.c
fs/nilfs2/inode.c
fs/nilfs2/segment.c
fs/nilfs2/the_nilfs.h
fs/ntfs/dir.c
fs/ocfs2/file.c
fs/open.c
fs/overlayfs/readdir.c
fs/proc/base.c
fs/proc/kcore.c
fs/readdir.c
fs/smb/client/cifs_debug.c
fs/smb/client/dfs.c
fs/smb/client/file.c
fs/smb/client/fs_context.c
fs/smb/server/smb2misc.c
fs/smb/server/smb2pdu.c
fs/vboxsf/dir.c
fs/vboxsf/shfl_hostintf.h
fs/zonefs/file.c
fs/zonefs/super.c
fs/zonefs/zonefs.h
include/acpi/acnames.h
include/acpi/acpi_bus.h
include/acpi/acpixf.h
include/acpi/actbl1.h
include/acpi/actbl2.h
include/acpi/actbl3.h
include/acpi/pdc_intel.h [deleted file]
include/acpi/platform/aclinux.h
include/acpi/platform/aczephyr.h
include/acpi/proc_cap_intel.h [new file with mode: 0644]
include/asm-generic/mshyperv.h
include/asm-generic/word-at-a-time.h
include/drm/drm_edid.h
include/linux/bio.h
include/linux/blkdev.h
include/linux/cpu.h
include/linux/cpumask.h
include/linux/fs.h
include/linux/hyperv.h
include/linux/intel_rapl.h
include/linux/prefetch.h
include/linux/serial_core.h
include/linux/skmsg.h
include/linux/spi/corgi_lcd.h
include/linux/spi/spi-mem.h
include/linux/thermal.h
include/linux/tpm.h
include/linux/virtio_net.h
include/net/cfg80211.h
include/net/gro.h
include/net/inet_sock.h
include/net/ip.h
include/net/netfilter/nf_tables.h
include/net/route.h
include/net/sock.h
include/net/vxlan.h
include/net/xfrm.h
include/scsi/scsi_device.h
include/soc/tegra/mc.h
include/trace/events/tcp.h
include/uapi/linux/pkt_cls.h
include/video/kyro.h
io_uring/io_uring.c
io_uring/openclose.c
kernel/bpf/cpumap.c
kernel/power/hibernate.c
kernel/trace/bpf_trace.c
kernel/workqueue.c
lib/Kconfig.debug
lib/Makefile
lib/cpumask.c
lib/scatterlist.c
lib/test_bitmap.c
mm/compaction.c
mm/damon/core.c
mm/hugetlb.c
mm/ksm.c
mm/memory-failure.c
mm/memory.c
mm/swapfile.c
mm/zsmalloc.c
net/can/raw.c
net/ceph/osd_client.c
net/core/bpf_sk_storage.c
net/core/filter.c
net/core/rtnetlink.c
net/core/skmsg.c
net/core/sock.c
net/core/sock_map.c
net/dcb/dcbnl.c
net/dccp/ipv6.c
net/dccp/output.c
net/dccp/proto.c
net/dsa/port.c
net/ipv4/inet_diag.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_tunnel_core.c
net/ipv4/ip_vti.c
net/ipv4/nexthop.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/Kconfig
net/ipv6/ip6_vti.c
net/ipv6/ip6mr.c
net/ipv6/ndisc.c
net/ipv6/ping.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipv6/udp_offload.c
net/key/af_key.c
net/l2tp/l2tp_ip6.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/sockopt.c
net/mptcp/subflow.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_proto_sctp.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_dynset.c
net/netfilter/nft_set_hash.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_rbtree.c
net/netfilter/nft_socket.c
net/netfilter/xt_socket.c
net/openvswitch/datapath.c
net/packet/af_packet.c
net/sched/cls_flower.c
net/sched/cls_fw.c
net/sched/cls_route.c
net/sched/cls_u32.c
net/sched/em_meta.c
net/sched/sch_taprio.c
net/smc/af_smc.c
net/smc/smc.h
net/smc/smc_clc.c
net/smc/smc_core.c
net/smc/smc_sysctl.c
net/sunrpc/svcsock.c
net/sunrpc/xprtrdma/verbs.c
net/tls/tls_device.c
net/tls/tls_main.c
net/unix/af_unix.c
net/wireless/nl80211.c
net/wireless/scan.c
net/xdp/xsk.c
net/xfrm/xfrm_compat.c
net/xfrm/xfrm_input.c
net/xfrm/xfrm_interface_core.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
rust/Makefile
rust/bindings/bindings_helper.h
rust/kernel/allocator.rs
rust/kernel/sync/arc.rs
rust/kernel/types.rs
rust/macros/vtable.rs
scripts/kallsyms.c
security/keys/sysctl.c
security/selinux/ss/policydb.c
sound/pci/hda/patch_cs8409-tables.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/max98363.c
sound/soc/codecs/rt1308-sdw.c
sound/soc/codecs/rt5665.c
sound/soc/fsl/fsl_micfil.c
sound/soc/fsl/fsl_micfil.h
sound/soc/intel/boards/sof_sdw.c
sound/soc/intel/boards/sof_sdw_cs42l42.c
sound/soc/meson/axg-tdm-formatter.c
sound/soc/soc-pcm.c
sound/soc/sof/intel/hda-dai-ops.c
sound/soc/sof/intel/hda-dai.c
sound/soc/sof/intel/hda.h
sound/soc/sof/ipc3.c
sound/soc/sof/ipc4-topology.c
sound/usb/quirks-table.h
tools/arch/arm64/include/uapi/asm/bitsperlong.h [new file with mode: 0644]
tools/arch/riscv/include/uapi/asm/bitsperlong.h [new file with mode: 0644]
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/msr-index.h
tools/counter/Makefile
tools/hv/vmbus_testing
tools/objtool/arch/x86/decode.c
tools/objtool/check.c
tools/objtool/include/objtool/arch.h
tools/objtool/include/objtool/elf.h
tools/perf/arch/arm64/util/pmu.c
tools/perf/arch/powerpc/util/skip-callchain-idx.c
tools/perf/tests/parse-events.c
tools/perf/tests/shell/test_uprobe_from_different_cu.sh
tools/perf/util/machine.c
tools/perf/util/parse-events.c
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/pmus.c
tools/perf/util/stat-display.c
tools/perf/util/thread-stack.c
tools/testing/radix-tree/regression1.c
tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
tools/testing/selftests/bpf/progs/test_sockmap_listen.c
tools/testing/selftests/cgroup/test_kmem.c
tools/testing/selftests/mm/ksm_tests.c
tools/testing/selftests/net/fib_nexthops.sh
tools/testing/selftests/net/forwarding/bridge_mdb.sh
tools/testing/selftests/net/forwarding/bridge_mdb_max.sh
tools/testing/selftests/net/forwarding/ethtool.sh
tools/testing/selftests/net/forwarding/ethtool_extended_state.sh
tools/testing/selftests/net/forwarding/ethtool_mm.sh
tools/testing/selftests/net/forwarding/hw_stats_l3_gre.sh
tools/testing/selftests/net/forwarding/ip6_forward_instats_vrf.sh
tools/testing/selftests/net/forwarding/lib.sh
tools/testing/selftests/net/forwarding/mirror_gre_changes.sh
tools/testing/selftests/net/forwarding/settings [new file with mode: 0644]
tools/testing/selftests/net/forwarding/tc_actions.sh
tools/testing/selftests/net/forwarding/tc_flower.sh
tools/testing/selftests/net/forwarding/tc_flower_l2_miss.sh
tools/testing/selftests/net/forwarding/tc_tunnel_key.sh
tools/testing/selftests/net/mptcp/mptcp_join.sh
tools/testing/selftests/net/pmtu.sh
tools/testing/selftests/net/so_incoming_cpu.c
tools/testing/selftests/riscv/vector/vstate_exec_nolibc.c
tools/testing/selftests/rseq/Makefile
tools/testing/selftests/rseq/rseq.c
tools/testing/selftests/tc-testing/tc-tests/qdiscs/taprio.json
tools/testing/vsock/Makefile

index 5dd31812198276e13c5c1be7e418cdf4a02f7708..e50662536c486512bc828cc0f15c9fac0814e0d8 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -538,6 +538,8 @@ Shuah Khan <shuah@kernel.org> <shuah.kh@samsung.com>
 Sibi Sankar <quic_sibis@quicinc.com> <sibis@codeaurora.org>
 Sid Manning <quic_sidneym@quicinc.com> <sidneym@codeaurora.org>
 Simon Arlott <simon@octiron.net> <simon@fire.lp0.eu>
+Simon Horman <horms@kernel.org> <simon.horman@corigine.com>
+Simon Horman <horms@kernel.org> <simon.horman@netronome.com>
 Simon Kelley <simon@thekelleys.org.uk>
 Sricharan Ramabadhran <quic_srichara@quicinc.com> <sricharan@codeaurora.org>
 Srinivas Ramana <quic_sramana@quicinc.com> <sramana@codeaurora.org>
index 6350dd82b9a9ceb028eaa7a5145a9dcce3413a12..087f762ebfd534e171434833fda4d772bd04ec1f 100644 (file)
@@ -82,7 +82,12 @@ Description:
                whether it resides in persistent capacity, volatile capacity,
                or the LSA, is made permanently unavailable by whatever means
                is appropriate for the media type. This functionality requires
-               the device to be not be actively decoding any HPA ranges.
+               the device to be disabled, that is, not actively decoding any
+               HPA ranges. This permits avoiding explicit global CPU cache
+               management, relying instead for it to be done when a region
+               transitions between software programmed and hardware committed
+               states. If this file is not present, then there is no hardware
+               support for the operation.
 
 
 What            /sys/bus/cxl/devices/memX/security/erase
@@ -92,7 +97,13 @@ Contact:        linux-cxl@vger.kernel.org
 Description:
                (WO) Write a boolean 'true' string value to this attribute to
                secure erase user data by changing the media encryption keys for
-               all user data areas of the device.
+               all user data areas of the device. This functionality requires
+               the device to be disabled, that is, not actively decoding any
+               HPA ranges. This permits avoiding explicit global CPU cache
+               management, relying instead for it to be done when a region
+               transitions between software programmed and hardware committed
+               states. If this file is not present, then there is no hardware
+               support for the operation.
 
 
 What:          /sys/bus/cxl/devices/memX/firmware/
index ecd585ca2d503853e3c2e8cdfa61551be999044e..77942eedf4f69055134a7c654b49acdfd02948c9 100644 (file)
@@ -513,17 +513,18 @@ Description:      information about CPUs heterogeneity.
                cpu_capacity: capacity of cpuX.
 
 What:          /sys/devices/system/cpu/vulnerabilities
+               /sys/devices/system/cpu/vulnerabilities/gather_data_sampling
+               /sys/devices/system/cpu/vulnerabilities/itlb_multihit
+               /sys/devices/system/cpu/vulnerabilities/l1tf
+               /sys/devices/system/cpu/vulnerabilities/mds
                /sys/devices/system/cpu/vulnerabilities/meltdown
+               /sys/devices/system/cpu/vulnerabilities/mmio_stale_data
+               /sys/devices/system/cpu/vulnerabilities/retbleed
+               /sys/devices/system/cpu/vulnerabilities/spec_store_bypass
                /sys/devices/system/cpu/vulnerabilities/spectre_v1
                /sys/devices/system/cpu/vulnerabilities/spectre_v2
-               /sys/devices/system/cpu/vulnerabilities/spec_store_bypass
-               /sys/devices/system/cpu/vulnerabilities/l1tf
-               /sys/devices/system/cpu/vulnerabilities/mds
                /sys/devices/system/cpu/vulnerabilities/srbds
                /sys/devices/system/cpu/vulnerabilities/tsx_async_abort
-               /sys/devices/system/cpu/vulnerabilities/itlb_multihit
-               /sys/devices/system/cpu/vulnerabilities/mmio_stale_data
-               /sys/devices/system/cpu/vulnerabilities/retbleed
 Date:          January 2018
 Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
 Description:   Information about CPU vulnerabilities
index fca40a54df5972a05957303cf8a3d4ef38d5b2a8..a80aeda85ef61884d132f9f90dc757c323dc37bb 100644 (file)
@@ -2,7 +2,7 @@ What:           /sys/devices/platform/hidma-*/chid
                /sys/devices/platform/QCOM8061:*/chid
 Date:          Dec 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Contains the ID of the channel within the HIDMA instance.
                It is used to associate a given HIDMA channel with the
index 3b6c5c9eabdc6a72e544e56041d0c12689bd7b69..0373745b4e186a54f833f1962439979247233f33 100644 (file)
@@ -2,7 +2,7 @@ What:           /sys/devices/platform/hidma-mgmt*/chanops/chan*/priority
                /sys/devices/platform/QCOM8060:*/chanops/chan*/priority
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Contains either 0 or 1 and indicates if the DMA channel is a
                low priority (0) or high priority (1) channel.
@@ -11,7 +11,7 @@ What:         /sys/devices/platform/hidma-mgmt*/chanops/chan*/weight
                /sys/devices/platform/QCOM8060:*/chanops/chan*/weight
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Contains 0..15 and indicates the weight of the channel among
                equal priority channels during round robin scheduling.
@@ -20,7 +20,7 @@ What:         /sys/devices/platform/hidma-mgmt*/chreset_timeout_cycles
                /sys/devices/platform/QCOM8060:*/chreset_timeout_cycles
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Contains the platform specific cycle value to wait after a
                reset command is issued. If the value is chosen too short,
@@ -32,7 +32,7 @@ What:         /sys/devices/platform/hidma-mgmt*/dma_channels
                /sys/devices/platform/QCOM8060:*/dma_channels
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Contains the number of dma channels supported by one instance
                of HIDMA hardware. The value may change from chip to chip.
@@ -41,7 +41,7 @@ What:         /sys/devices/platform/hidma-mgmt*/hw_version_major
                /sys/devices/platform/QCOM8060:*/hw_version_major
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Version number major for the hardware.
 
@@ -49,7 +49,7 @@ What:         /sys/devices/platform/hidma-mgmt*/hw_version_minor
                /sys/devices/platform/QCOM8060:*/hw_version_minor
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Version number minor for the hardware.
 
@@ -57,7 +57,7 @@ What:         /sys/devices/platform/hidma-mgmt*/max_rd_xactions
                /sys/devices/platform/QCOM8060:*/max_rd_xactions
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Contains a value between 0 and 31. Maximum number of
                read transactions that can be issued back to back.
@@ -69,7 +69,7 @@ What:         /sys/devices/platform/hidma-mgmt*/max_read_request
                /sys/devices/platform/QCOM8060:*/max_read_request
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Size of each read request. The value needs to be a power
                of two and can be between 128 and 1024.
@@ -78,7 +78,7 @@ What:         /sys/devices/platform/hidma-mgmt*/max_wr_xactions
                /sys/devices/platform/QCOM8060:*/max_wr_xactions
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Contains a value between 0 and 31. Maximum number of
                write transactions that can be issued back to back.
@@ -91,7 +91,7 @@ What:         /sys/devices/platform/hidma-mgmt*/max_write_request
                /sys/devices/platform/QCOM8060:*/max_write_request
 Date:          Nov 2015
 KernelVersion: 4.4
-Contact:       "Sinan Kaya <okaya@codeaurora.org>"
+Contact:       "Sinan Kaya <okaya@kernel.org>"
 Description:
                Size of each write request. The value needs to be a power
                of two and can be between 128 and 1024.
diff --git a/Documentation/admin-guide/hw-vuln/gather_data_sampling.rst b/Documentation/admin-guide/hw-vuln/gather_data_sampling.rst
new file mode 100644 (file)
index 0000000..264bfa9
--- /dev/null
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+GDS - Gather Data Sampling
+==========================
+
+Gather Data Sampling is a hardware vulnerability which allows unprivileged
+speculative access to data which was previously stored in vector registers.
+
+Problem
+-------
+When a gather instruction performs loads from memory, different data elements
+are merged into the destination vector register. However, when a gather
+instruction that is transiently executed encounters a fault, stale data from
+architectural or internal vector registers may get transiently forwarded to the
+destination vector register instead. This will allow a malicious attacker to
+infer stale data using typical side channel techniques like cache timing
+attacks. GDS is a purely sampling-based attack.
+
+The attacker uses gather instructions to infer the stale vector register data.
+The victim does not need to do anything special other than use the vector
+registers. The victim does not need to use gather instructions to be
+vulnerable.
+
+Because the buffers are shared between Hyper-Threads cross Hyper-Thread attacks
+are possible.
+
+Attack scenarios
+----------------
+Without mitigation, GDS can infer stale data across virtually all
+permission boundaries:
+
+       Non-enclaves can infer SGX enclave data
+       Userspace can infer kernel data
+       Guests can infer data from hosts
+       Guest can infer guest from other guests
+       Users can infer data from other users
+
+Because of this, it is important to ensure that the mitigation stays enabled in
+lower-privilege contexts like guests and when running outside SGX enclaves.
+
+The hardware enforces the mitigation for SGX. Likewise, VMMs should  ensure
+that guests are not allowed to disable the GDS mitigation. If a host erred and
+allowed this, a guest could theoretically disable GDS mitigation, mount an
+attack, and re-enable it.
+
+Mitigation mechanism
+--------------------
+This issue is mitigated in microcode. The microcode defines the following new
+bits:
+
+ ================================   ===   ============================
+ IA32_ARCH_CAPABILITIES[GDS_CTRL]   R/O   Enumerates GDS vulnerability
+                                          and mitigation support.
+ IA32_ARCH_CAPABILITIES[GDS_NO]     R/O   Processor is not vulnerable.
+ IA32_MCU_OPT_CTRL[GDS_MITG_DIS]    R/W   Disables the mitigation
+                                          0 by default.
+ IA32_MCU_OPT_CTRL[GDS_MITG_LOCK]   R/W   Locks GDS_MITG_DIS=0. Writes
+                                          to GDS_MITG_DIS are ignored
+                                          Can't be cleared once set.
+ ================================   ===   ============================
+
+GDS can also be mitigated on systems that don't have updated microcode by
+disabling AVX. This can be done by setting gather_data_sampling="force" or
+"clearcpuid=avx" on the kernel command-line.
+
+If used, these options will disable AVX use by turning off XSAVE YMM support.
+However, the processor will still enumerate AVX support.  Userspace that
+does not follow proper AVX enumeration to check both AVX *and* XSAVE YMM
+support will break.
+
+Mitigation control on the kernel command line
+---------------------------------------------
+The mitigation can be disabled by setting "gather_data_sampling=off" or
+"mitigations=off" on the kernel command line. Not specifying either will default
+to the mitigation being enabled. Specifying "gather_data_sampling=force" will
+use the microcode mitigation when available or disable AVX on affected systems
+where the microcode hasn't been updated to include the mitigation.
+
+GDS System Information
+------------------------
+The kernel provides vulnerability status information through sysfs. For
+GDS this can be accessed by the following sysfs file:
+
+/sys/devices/system/cpu/vulnerabilities/gather_data_sampling
+
+The possible values contained in this file are:
+
+ ============================== =============================================
+ Not affected                   Processor not vulnerable.
+ Vulnerable                     Processor vulnerable and mitigation disabled.
+ Vulnerable: No microcode       Processor vulnerable and microcode is missing
+                                mitigation.
+ Mitigation: AVX disabled,
+ no microcode                   Processor is vulnerable and microcode is missing
+                                mitigation. AVX disabled as mitigation.
+ Mitigation: Microcode          Processor is vulnerable and mitigation is in
+                                effect.
+ Mitigation: Microcode (locked) Processor is vulnerable and mitigation is in
+                                effect and cannot be disabled.
+ Unknown: Dependent on
+ hypervisor status              Running on a virtual guest processor that is
+                                affected but with no way to know if host
+                                processor is mitigated or vulnerable.
+ ============================== =============================================
+
+GDS Default mitigation
+----------------------
+The updated microcode will enable the mitigation by default. The kernel's
+default action is to leave the mitigation enabled.
index e0614760a99e7e919b8052003a61f5d9609c2a87..de99caabf65a3f3ba3a35dd947236195e9dcebfa 100644 (file)
@@ -13,9 +13,11 @@ are configurable at compile, boot or run time.
    l1tf
    mds
    tsx_async_abort
-   multihit.rst
-   special-register-buffer-data-sampling.rst
-   core-scheduling.rst
-   l1d_flush.rst
-   processor_mmio_stale_data.rst
-   cross-thread-rsb.rst
+   multihit
+   special-register-buffer-data-sampling
+   core-scheduling
+   l1d_flush
+   processor_mmio_stale_data
+   cross-thread-rsb
+   srso
+   gather_data_sampling
diff --git a/Documentation/admin-guide/hw-vuln/srso.rst b/Documentation/admin-guide/hw-vuln/srso.rst
new file mode 100644 (file)
index 0000000..b6cfb51
--- /dev/null
@@ -0,0 +1,150 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Speculative Return Stack Overflow (SRSO)
+========================================
+
+This is a mitigation for the speculative return stack overflow (SRSO)
+vulnerability found on AMD processors. The mechanism is by now the well
+known scenario of poisoning CPU functional units - the Branch Target
+Buffer (BTB) and Return Address Predictor (RAP) in this case - and then
+tricking the elevated privilege domain (the kernel) into leaking
+sensitive data.
+
+AMD CPUs predict RET instructions using a Return Address Predictor (aka
+Return Address Stack/Return Stack Buffer). In some cases, a non-architectural
+CALL instruction (i.e., an instruction predicted to be a CALL but is
+not actually a CALL) can create an entry in the RAP which may be used
+to predict the target of a subsequent RET instruction.
+
+The specific circumstances that lead to this varies by microarchitecture
+but the concern is that an attacker can mis-train the CPU BTB to predict
+non-architectural CALL instructions in kernel space and use this to
+control the speculative target of a subsequent kernel RET, potentially
+leading to information disclosure via a speculative side-channel.
+
+The issue is tracked under CVE-2023-20569.
+
+Affected processors
+-------------------
+
+AMD Zen, generations 1-4. That is, all families 0x17 and 0x19. Older
+processors have not been investigated.
+
+System information and options
+------------------------------
+
+First of all, it is required that the latest microcode be loaded for
+mitigations to be effective.
+
+The sysfs file showing SRSO mitigation status is:
+
+  /sys/devices/system/cpu/vulnerabilities/spec_rstack_overflow
+
+The possible values in this file are:
+
+ * 'Not affected':
+
+   The processor is not vulnerable
+
+ * 'Vulnerable: no microcode':
+
+   The processor is vulnerable, no microcode extending IBPB
+   functionality to address the vulnerability has been applied.
+
+ * 'Mitigation: microcode':
+
+   Extended IBPB functionality microcode patch has been applied. It does
+   not address User->Kernel and Guest->Host transitions protection but it
+   does address User->User and VM->VM attack vectors.
+
+   Note that User->User mitigation is controlled by how the IBPB aspect in
+   the Spectre v2 mitigation is selected:
+
+    * conditional IBPB:
+
+      where each process can select whether it needs an IBPB issued
+      around it PR_SPEC_DISABLE/_ENABLE etc, see :doc:`spectre`
+
+    * strict:
+
+      i.e., always on - by supplying spectre_v2_user=on on the kernel
+      command line
+
+   (spec_rstack_overflow=microcode)
+
+ * 'Mitigation: safe RET':
+
+   Software-only mitigation. It complements the extended IBPB microcode
+   patch functionality by addressing User->Kernel and Guest->Host
+   transitions protection.
+
+   Selected by default or by spec_rstack_overflow=safe-ret
+
+ * 'Mitigation: IBPB':
+
+   Similar protection as "safe RET" above but employs an IBPB barrier on
+   privilege domain crossings (User->Kernel, Guest->Host).
+
+  (spec_rstack_overflow=ibpb)
+
+ * 'Mitigation: IBPB on VMEXIT':
+
+   Mitigation addressing the cloud provider scenario - the Guest->Host
+   transitions only.
+
+   (spec_rstack_overflow=ibpb-vmexit)
+
+
+
+In order to exploit vulnerability, an attacker needs to:
+
+ - gain local access on the machine
+
+ - break kASLR
+
+ - find gadgets in the running kernel in order to use them in the exploit
+
+ - potentially create and pin an additional workload on the sibling
+   thread, depending on the microarchitecture (not necessary on fam 0x19)
+
+ - run the exploit
+
+Considering the performance implications of each mitigation type, the
+default one is 'Mitigation: safe RET' which should take care of most
+attack vectors, including the local User->Kernel one.
+
+As always, the user is advised to keep her/his system up-to-date by
+applying software updates regularly.
+
+The default setting will be reevaluated when needed and especially when
+new attack vectors appear.
+
+As one can surmise, 'Mitigation: safe RET' does come at the cost of some
+performance depending on the workload. If one trusts her/his userspace
+and does not want to suffer the performance impact, one can always
+disable the mitigation with spec_rstack_overflow=off.
+
+Similarly, 'Mitigation: IBPB' is another full mitigation type employing
+an indrect branch prediction barrier after having applied the required
+microcode patch for one's system. This mitigation comes also at
+a performance cost.
+
+Mitigation: safe RET
+--------------------
+
+The mitigation works by ensuring all RET instructions speculate to
+a controlled location, similar to how speculation is controlled in the
+retpoline sequence.  To accomplish this, the __x86_return_thunk forces
+the CPU to mispredict every function return using a 'safe return'
+sequence.
+
+To ensure the safety of this mitigation, the kernel must ensure that the
+safe return sequence is itself free from attacker interference.  In Zen3
+and Zen4, this is accomplished by creating a BTB alias between the
+untraining function srso_alias_untrain_ret() and the safe return
+function srso_alias_safe_ret() which results in evicting a potentially
+poisoned BTB entry and using that safe one for all function returns.
+
+In older Zen1 and Zen2, this is accomplished using a reinterpretation
+technique similar to Retbleed one: srso_untrain_ret() and
+srso_safe_ret().
index c18d94fa64704820abd32ba39c8dee0025e2f187..f8ebb63b6c5d2d3b5a5d9ee9a300782f92b16061 100644 (file)
@@ -624,3 +624,9 @@ Used to get the correct ranges:
   * VMALLOC_START ~ VMALLOC_END : vmalloc() / ioremap() space.
   * VMEMMAP_START ~ VMEMMAP_END : vmemmap space, used for struct page array.
   * KERNEL_LINK_ADDR : start address of Kernel link and BPF
+
+va_kernel_pa_offset
+-------------------
+
+Indicates the offset between the kernel virtual and physical mappings.
+Used to translate virtual to physical addresses.
index a1457995fd41cfb7db6cfa0cbb816fb9bbcd7fc0..23ebe34ff901e887cb72a9ab735520c7148e4091 100644 (file)
                        Format: off | on
                        default: on
 
+       gather_data_sampling=
+                       [X86,INTEL] Control the Gather Data Sampling (GDS)
+                       mitigation.
+
+                       Gather Data Sampling is a hardware vulnerability which
+                       allows unprivileged speculative access to data which was
+                       previously stored in vector registers.
+
+                       This issue is mitigated by default in updated microcode.
+                       The mitigation may have a performance impact but can be
+                       disabled. On systems without the microcode mitigation
+                       disabling AVX serves as a mitigation.
+
+                       force:  Disable AVX to mitigate systems without
+                               microcode mitigation. No effect if the microcode
+                               mitigation is present. Known to cause crashes in
+                               userspace with buggy AVX enumeration.
+
+                       off:    Disable GDS mitigation.
+
        gcov_persist=   [GCOV] When non-zero (default), profiling data for
                        kernel modules is saved and remains accessible via
                        debugfs, even when the module is unloaded/reloaded.
                                Disable all optional CPU mitigations.  This
                                improves system performance, but it may also
                                expose users to several CPU vulnerabilities.
-                               Equivalent to: nopti [X86,PPC]
-                                              if nokaslr then kpti=0 [ARM64]
-                                              nospectre_v1 [X86,PPC]
-                                              nobp=0 [S390]
-                                              nospectre_v2 [X86,PPC,S390,ARM64]
-                                              spectre_v2_user=off [X86]
-                                              spec_store_bypass_disable=off [X86,PPC]
-                                              ssbd=force-off [ARM64]
-                                              nospectre_bhb [ARM64]
+                               Equivalent to: if nokaslr then kpti=0 [ARM64]
+                                              gather_data_sampling=off [X86]
+                                              kvm.nx_huge_pages=off [X86]
                                               l1tf=off [X86]
                                               mds=off [X86]
-                                              tsx_async_abort=off [X86]
-                                              kvm.nx_huge_pages=off [X86]
-                                              srbds=off [X86,INTEL]
+                                              mmio_stale_data=off [X86]
                                               no_entry_flush [PPC]
                                               no_uaccess_flush [PPC]
-                                              mmio_stale_data=off [X86]
+                                              nobp=0 [S390]
+                                              nopti [X86,PPC]
+                                              nospectre_bhb [ARM64]
+                                              nospectre_v1 [X86,PPC]
+                                              nospectre_v2 [X86,PPC,S390,ARM64]
                                               retbleed=off [X86]
+                                              spec_store_bypass_disable=off [X86,PPC]
+                                              spectre_v2_user=off [X86]
+                                              srbds=off [X86,INTEL]
+                                              ssbd=force-off [ARM64]
+                                              tsx_async_abort=off [X86]
 
                                Exceptions:
                                               This does not have any effect on
                        Not specifying this option is equivalent to
                        spectre_v2_user=auto.
 
+       spec_rstack_overflow=
+                       [X86] Control RAS overflow mitigation on AMD Zen CPUs
+
+                       off             - Disable mitigation
+                       microcode       - Enable microcode mitigation only
+                       safe-ret        - Enable sw-only safe RET mitigation (default)
+                       ibpb            - Enable mitigation by issuing IBPB on
+                                         kernel entry
+                       ibpb-vmexit     - Issue IBPB only on VMEXIT
+                                         (cloud-specific mitigation)
+
        spec_store_bypass_disable=
                        [HW] Control Speculative Store Bypass (SSB) Disable mitigation
                        (Speculative Store Bypass vulnerability)
                        -1: disable all critical trip points in all thermal zones
                        <degrees C>: override all critical trip points
 
-       thermal.nocrt=  [HW,ACPI]
-                       Set to disable actions on ACPI thermal zone
-                       critical and hot trip points.
-
        thermal.off=    [HW,ACPI]
                        1: disable ACPI thermal control
 
index 72d2e910f2065309f89eb8916da8755ca6815934..2594fa192f93d0d298cc3a9e7171a584e78b756d 100644 (file)
@@ -216,7 +216,6 @@ properties:
     description: Whether to enable burnout current for EXT1.
 
   adi,ext1-burnout-current-nanoamp:
-    $ref: /schemas/types.yaml#/definitions/uint32
     description:
       Burnout current in nanoamps to be applied to EXT1.
     enum: [0, 50, 500, 1000, 10000]
@@ -233,7 +232,6 @@ properties:
     description: Whether to enable burnout current for EXT2.
 
   adi,ext2-burnout-current-nanoamp:
-    $ref: /schemas/types.yaml#/definitions/uint32
     description: Burnout current in nanoamps to be applied to EXT2.
     enum: [0, 50, 500, 1000, 10000]
     default: 0
@@ -249,7 +247,6 @@ properties:
     description: Whether to enable burnout current for VIOUT.
 
   adi,viout-burnout-current-nanoamp:
-    $ref: /schemas/types.yaml#/definitions/uint32
     description: Burnout current in nanoamps to be applied to VIOUT.
     enum: [0, 1000, 10000]
     default: 0
index acb2b2ac4fe1eb6830abd6e94d09e07ae22edb51..31cc0c412805c941f44bfb1b61be141dbc780588 100644 (file)
@@ -293,7 +293,7 @@ allOf:
 patternProperties:
   "^mac@[0-1]$":
     type: object
-    additionalProperties: false
+    unevaluatedProperties: false
     allOf:
       - $ref: ethernet-controller.yaml#
     description:
@@ -305,14 +305,9 @@ patternProperties:
       reg:
         maxItems: 1
 
-      phy-handle: true
-
-      phy-mode: true
-
     required:
       - reg
       - compatible
-      - phy-handle
 
 required:
   - compatible
index 176ea5f90251af1ffd6ee2cc3c3dc458d04b67b9..7f324c6da915dd86bdd8a36f1f0f487c0184513d 100644 (file)
@@ -91,12 +91,18 @@ properties:
     $ref: /schemas/types.yaml#/definitions/phandle
 
   tx_delay:
-    description: Delay value for TXD timing. Range value is 0~0x7F, 0x30 as default.
+    description: Delay value for TXD timing.
     $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 0x7F
+    default: 0x30
 
   rx_delay:
-    description: Delay value for RXD timing. Range value is 0~0x7F, 0x10 as default.
+    description: Delay value for RXD timing.
     $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 0x7F
+    default: 0x10
 
   phy-supply:
     description: PHY regulator
index e608a4f1bcaec78f0192c8567a61476a66a928ad..e119a226a4b18363f5337b59a02075d93320d539 100644 (file)
@@ -87,7 +87,7 @@ $defs:
                 emac0_mdc, emac0_mdio, emac0_ptp_aux, emac0_ptp_pps, emac1_mcg0,
                 emac1_mcg1, emac1_mcg2, emac1_mcg3, emac1_mdc, emac1_mdio,
                 emac1_ptp_aux, emac1_ptp_pps, gcc_gp1, gcc_gp2, gcc_gp3,
-                gcc_gp4, gcc_gp5, hs0_mi2s, hs1_mi2s, hs2_mi2s, ibi_i3c,
+                gcc_gp4, gcc_gp5, gpio, hs0_mi2s, hs1_mi2s, hs2_mi2s, ibi_i3c,
                 jitter_bist, mdp0_vsync0, mdp0_vsync1, mdp0_vsync2, mdp0_vsync3,
                 mdp0_vsync4, mdp0_vsync5, mdp0_vsync6, mdp0_vsync7, mdp0_vsync8,
                 mdp1_vsync0, mdp1_vsync1, mdp1_vsync2, mdp1_vsync3, mdp1_vsync4,
index 30b2131b586018f663e17750bb428e2a48798633..65cb2e5c5eee08a0555092823edd5606cd7aa735 100644 (file)
@@ -16,13 +16,15 @@ properties:
       - enum:
           - atmel,at91rm9200-usart
           - atmel,at91sam9260-usart
-          - microchip,sam9x60-usart
       - items:
           - const: atmel,at91rm9200-dbgu
           - const: atmel,at91rm9200-usart
       - items:
           - const: atmel,at91sam9260-dbgu
           - const: atmel,at91sam9260-usart
+      - items:
+          - const: microchip,sam9x60-usart
+          - const: atmel,at91sam9260-usart
       - items:
           - const: microchip,sam9x60-dbgu
           - const: microchip,sam9x60-usart
index ed148919e11ad5e49ecd569110f8cabf7541607e..0ca479dbb1cd1f5e5b5199c93078b3b2e9e50fd3 100644 (file)
@@ -551,9 +551,8 @@ mutex or just to use i_size_read() instead.
 Note: this does not protect the file->f_pos against concurrent modifications
 since this is something the userspace has to take care about.
 
-->iterate() is called with i_rwsem exclusive.
-
-->iterate_shared() is called with i_rwsem at least shared.
+->iterate_shared() is called with i_rwsem held for reading, and with the
+file f_pos_lock held exclusively
 
 ->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags.
 Most instances call fasync_helper(), which does that maintenance, so it's
index d2d684ae77984f066b96fe028477fc5aec2e31ec..0f5da78ef4f905fad890799389d92b97e13d9e94 100644 (file)
@@ -537,7 +537,7 @@ vfs_readdir() is gone; switch to iterate_dir() instead
 
 **mandatory**
 
-->readdir() is gone now; switch to ->iterate()
+->readdir() is gone now; switch to ->iterate_shared()
 
 **mandatory**
 
@@ -693,24 +693,19 @@ parallel now.
 
 ---
 
-**recommended**
+**mandatory**
 
-->iterate_shared() is added; it's a parallel variant of ->iterate().
+->iterate_shared() is added.
 Exclusion on struct file level is still provided (as well as that
 between it and lseek on the same struct file), but if your directory
 has been opened several times, you can get these called in parallel.
 Exclusion between that method and all directory-modifying ones is
 still provided, of course.
 
-Often enough ->iterate() can serve as ->iterate_shared() without any
-changes - it is a read-only operation, after all.  If you have any
-per-inode or per-dentry in-core data structures modified by ->iterate(),
-you might need something to serialize the access to them.  If you
-do dcache pre-seeding, you'll need to switch to d_alloc_parallel() for
-that; look for in-tree examples.
-
-Old method is only used if the new one is absent; eventually it will
-be removed.  Switch while you still can; the old one won't stay.
+If you have any per-inode or per-dentry in-core data structures modified
+by ->iterate_shared(), you might need something to serialize the access
+to them.  If you do dcache pre-seeding, you'll need to switch to
+d_alloc_parallel() for that; look for in-tree examples.
 
 ---
 
@@ -930,9 +925,9 @@ should be done by looking at FMODE_LSEEK in file->f_mode.
 filldir_t (readdir callbacks) calling conventions have changed.  Instead of
 returning 0 or -E... it returns bool now.  false means "no more" (as -E... used
 to) and true - "keep going" (as 0 in old calling conventions).  Rationale:
-callers never looked at specific -E... values anyway.  ->iterate() and
-->iterate_shared() instance require no changes at all, all filldir_t ones in
-the tree converted.
+callers never looked at specific -E... values anyway. -> iterate_shared()
+instances require no changes at all, all filldir_t ones in the tree
+converted.
 
 ---
 
index b7d3ae7458f8686ac8dd194eb44b76fe4af65b73..41ddc10f1ac7b5dd860a829a4723b25b47ae5c4d 100644 (file)
@@ -46,7 +46,7 @@ driver model device node, and its I2C address.
        },
 
        .id_table       = foo_idtable,
-       .probe_new      = foo_probe,
+       .probe          = foo_probe,
        .remove         = foo_remove,
        /* if device autodetection is needed: */
        .class          = I2C_CLASS_SOMETHING,
index 8b1045c3b59e0ef0675d0ed113139b4e84b8b81d..c383a394c6656989fb7c8e7c43d4b5eca8909d42 100644 (file)
@@ -178,10 +178,10 @@ nf_conntrack_sctp_timeout_established - INTEGER (seconds)
        Default is set to (hb_interval * path_max_retrans + rto_max)
 
 nf_conntrack_sctp_timeout_shutdown_sent - INTEGER (seconds)
-       default 0.3
+       default 3
 
 nf_conntrack_sctp_timeout_shutdown_recd - INTEGER (seconds)
-       default 0.3
+       default 3
 
 nf_conntrack_sctp_timeout_shutdown_ack_sent - INTEGER (seconds)
        default 3
index 53b7ca8044659f9bb6ffa44ce4a61f09b73c84d5..d590ce31aa7266755a754a82230b99e14867e49e 100644 (file)
@@ -2339,7 +2339,7 @@ F:        drivers/phy/mediatek/
 ARM/MICROCHIP (ARM64) SoC support
 M:     Conor Dooley <conor@kernel.org>
 M:     Nicolas Ferre <nicolas.ferre@microchip.com>
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 T:     git https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git
@@ -2348,7 +2348,7 @@ F:        arch/arm64/boot/dts/microchip/
 ARM/Microchip (AT91) SoC support
 M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 W:     http://www.linux4sam.org
@@ -3250,7 +3250,7 @@ F:        include/uapi/linux/atm*
 
 ATMEL MACB ETHERNET DRIVER
 M:     Nicolas Ferre <nicolas.ferre@microchip.com>
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 S:     Supported
 F:     drivers/net/ethernet/cadence/
 
@@ -3262,9 +3262,8 @@ F:        Documentation/devicetree/bindings/input/atmel,maxtouch.yaml
 F:     drivers/input/touchscreen/atmel_mxt_ts.c
 
 ATMEL WIRELESS DRIVER
-M:     Simon Kelley <simon@thekelleys.org.uk>
 L:     linux-wireless@vger.kernel.org
-S:     Maintained
+S:     Orphan
 W:     http://www.thekelleys.org.uk/atmel
 W:     http://atmelwlandriver.sourceforge.net/
 F:     drivers/net/wireless/atmel/atmel*
@@ -3394,7 +3393,7 @@ F:        drivers/media/radio/radio-aztech*
 B43 WIRELESS DRIVER
 L:     linux-wireless@vger.kernel.org
 L:     b43-dev@lists.infradead.org
-S:     Odd Fixes
+S:     Orphan
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/b43
 F:     drivers/net/wireless/broadcom/b43/
 
@@ -5462,8 +5461,7 @@ F:        Documentation/devicetree/bindings/net/can/ctu,ctucanfd.yaml
 F:     drivers/net/can/ctucanfd/
 
 CW1200 WLAN driver
-M:     Solomon Peachy <pizza@shaftnet.org>
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/st/cw1200/
 
 CX18 VIDEO4LINUX DRIVER
@@ -8814,6 +8812,7 @@ R:        Michael Walle <michael@walle.cc>
 S:     Maintained
 F:     drivers/gpio/gpio-regmap.c
 F:     include/linux/gpio/regmap.h
+K:     (devm_)?gpio_regmap_(un)?register
 
 GPIO SUBSYSTEM
 M:     Linus Walleij <linus.walleij@linaro.org>
@@ -9377,7 +9376,6 @@ F:        drivers/crypto/hisilicon/sgl.c
 F:     include/linux/hisi_acc_qm.h
 
 HISILICON ROCE DRIVER
-M:     Haoyue Xu <xuhaoyue1@hisilicon.com>
 M:     Junxian Huang <huangjunxian6@hisilicon.com>
 L:     linux-rdma@vger.kernel.org
 S:     Maintained
@@ -9662,6 +9660,7 @@ F:        tools/hv/
 
 HYPERBUS SUPPORT
 M:     Vignesh Raghavendra <vigneshr@ti.com>
+R:     Tudor Ambarus <tudor.ambarus@linaro.org>
 L:     linux-mtd@lists.infradead.org
 S:     Supported
 Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
@@ -12481,6 +12480,7 @@ F:      net/mctp/
 
 MAPLE TREE
 M:     Liam R. Howlett <Liam.Howlett@oracle.com>
+L:     maple-tree@lists.infradead.org
 L:     linux-mm@kvack.org
 S:     Supported
 F:     Documentation/core-api/maple_tree.rst
@@ -12592,18 +12592,14 @@ F:    Documentation/devicetree/bindings/net/marvell,pp2.yaml
 F:     drivers/net/ethernet/marvell/mvpp2/
 
 MARVELL MWIFIEX WIRELESS DRIVER
-M:     Amitkumar Karwar <amitkarwar@gmail.com>
-M:     Ganapathi Bhat <ganapathi017@gmail.com>
-M:     Sharvari Harisangam <sharvari.harisangam@nxp.com>
-M:     Xinming Hu <huxinming820@gmail.com>
+M:     Brian Norris <briannorris@chromium.org>
 L:     linux-wireless@vger.kernel.org
-S:     Maintained
+S:     Odd Fixes
 F:     drivers/net/wireless/marvell/mwifiex/
 
 MARVELL MWL8K WIRELESS DRIVER
-M:     Lennert Buytenhek <buytenh@wantstofly.org>
 L:     linux-wireless@vger.kernel.org
-S:     Odd Fixes
+S:     Orphan
 F:     drivers/net/wireless/marvell/mwl8k.c
 
 MARVELL NAND CONTROLLER DRIVER
@@ -13791,7 +13787,7 @@ F:      Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
 F:     drivers/spi/spi-at91-usart.c
 
 MICROCHIP AUDIO ASOC DRIVERS
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 F:     Documentation/devicetree/bindings/sound/atmel*
@@ -13814,7 +13810,7 @@ S:      Maintained
 F:     drivers/crypto/atmel-ecc.*
 
 MICROCHIP EIC DRIVER
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     Documentation/devicetree/bindings/interrupt-controller/microchip,sama7g5-eic.yaml
@@ -13887,7 +13883,7 @@ F:      drivers/video/fbdev/atmel_lcdfb.c
 F:     include/video/atmel_lcdc.h
 
 MICROCHIP MCP16502 PMIC DRIVER
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
@@ -13914,7 +13910,7 @@ F:      Documentation/devicetree/bindings/mtd/atmel-nand.txt
 F:     drivers/mtd/nand/raw/atmel/*
 
 MICROCHIP OTPC DRIVER
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
@@ -13953,7 +13949,7 @@ F:      Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml
 F:     drivers/fpga/microchip-spi.c
 
 MICROCHIP PWM DRIVER
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-pwm@vger.kernel.org
 S:     Supported
@@ -13969,7 +13965,7 @@ F:      drivers/iio/adc/at91-sama5d2_adc.c
 F:     include/dt-bindings/iio/adc/at91-sama5d2_adc.h
 
 MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 S:     Supported
 F:     Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml
 F:     drivers/power/reset/at91-sama5d2_shdwc.c
@@ -13986,7 +13982,7 @@ S:      Supported
 F:     drivers/spi/spi-atmel.*
 
 MICROCHIP SSC DRIVER
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     Documentation/devicetree/bindings/misc/atmel-ssc.txt
@@ -14015,7 +14011,7 @@ F:      drivers/usb/gadget/udc/atmel_usba_udc.*
 
 MICROCHIP WILC1000 WIFI DRIVER
 M:     Ajay Singh <ajay.kathat@microchip.com>
-M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
 L:     linux-wireless@vger.kernel.org
 S:     Supported
 F:     drivers/net/wireless/microchip/wilc1000/
@@ -16298,6 +16294,7 @@ F:      drivers/pci/controller/dwc/pci-exynos.c
 PCI DRIVER FOR SYNOPSYS DESIGNWARE
 M:     Jingoo Han <jingoohan1@gmail.com>
 M:     Gustavo Pimentel <gustavo.pimentel@synopsys.com>
+M:     Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
 L:     linux-pci@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
@@ -17449,6 +17446,7 @@ F:      drivers/media/tuners/qt1010*
 
 QUALCOMM ATH12K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@kernel.org>
+M:     Jeff Johnson <quic_jjohnson@quicinc.com>
 L:     ath12k@lists.infradead.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
@@ -17456,6 +17454,7 @@ F:      drivers/net/wireless/ath/ath12k/
 
 QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@kernel.org>
+M:     Jeff Johnson <quic_jjohnson@quicinc.com>
 L:     ath10k@lists.infradead.org
 S:     Supported
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
@@ -17465,6 +17464,7 @@ F:      drivers/net/wireless/ath/ath10k/
 
 QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@kernel.org>
+M:     Jeff Johnson <quic_jjohnson@quicinc.com>
 L:     ath11k@lists.infradead.org
 S:     Supported
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/ath11k
@@ -17985,7 +17985,7 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.g
 F:     drivers/net/wireless/realtek/rtlwifi/
 
 REALTEK WIRELESS DRIVER (rtw88)
-M:     Yan-Hsuan Chuang <tony0620emma@gmail.com>
+M:     Ping-Ke Shih <pkshih@realtek.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wireless/realtek/rtw88/
@@ -18510,17 +18510,14 @@ RTL8180 WIRELESS DRIVER
 L:     linux-wireless@vger.kernel.org
 S:     Orphan
 W:     https://wireless.wiki.kernel.org/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
 F:     drivers/net/wireless/realtek/rtl818x/rtl8180/
 
 RTL8187 WIRELESS DRIVER
-M:     Herton Ronaldo Krzesinski <herton@canonical.com>
-M:     Hin-Tak Leung <htl10@users.sourceforge.net>
+M:     Hin-Tak Leung <hintak.leung@gmail.com>
 M:     Larry Finger <Larry.Finger@lwfinger.net>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 W:     https://wireless.wiki.kernel.org/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
 F:     drivers/net/wireless/realtek/rtl818x/rtl8187/
 
 RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
@@ -19227,13 +19224,6 @@ F:     Documentation/devicetree/bindings/serial/serial.yaml
 F:     drivers/tty/serdev/
 F:     include/linux/serdev.h
 
-SERIAL DRIVERS
-M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-L:     linux-serial@vger.kernel.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/serial/
-F:     drivers/tty/serial/
-
 SERIAL IR RECEIVER
 M:     Sean Young <sean@mess.org>
 L:     linux-media@vger.kernel.org
@@ -20404,7 +20394,6 @@ F:      drivers/pwm/pwm-stm32*
 F:     include/linux/*/stm32-*tim*
 
 STMMAC ETHERNET DRIVER
-M:     Giuseppe Cavallaro <peppe.cavallaro@st.com>
 M:     Alexandre Torgue <alexandre.torgue@foss.st.com>
 M:     Jose Abreu <joabreu@synopsys.com>
 L:     netdev@vger.kernel.org
@@ -21639,20 +21628,16 @@ W:    https://github.com/srcres258/linux-doc
 T:     git git://github.com/srcres258/linux-doc.git doc-zh-tw
 F:     Documentation/translations/zh_TW/
 
-TTY LAYER
+TTY LAYER AND SERIAL DRIVERS
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 M:     Jiri Slaby <jirislaby@kernel.org>
 L:     linux-kernel@vger.kernel.org
 L:     linux-serial@vger.kernel.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
+F:     Documentation/devicetree/bindings/serial/
 F:     Documentation/driver-api/serial/
 F:     drivers/tty/
-F:     drivers/tty/serial/serial_base.h
-F:     drivers/tty/serial/serial_base_bus.c
-F:     drivers/tty/serial/serial_core.c
-F:     drivers/tty/serial/serial_ctrl.c
-F:     drivers/tty/serial/serial_port.c
 F:     include/linux/selection.h
 F:     include/linux/serial.h
 F:     include/linux/serial_core.h
@@ -21681,11 +21666,14 @@ S:    Orphan
 F:     drivers/net/ethernet/dec/tulip/
 
 TUN/TAP driver
-M:     Maxim Krasnyansky <maxk@qti.qualcomm.com>
+M:     Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+M:     Jason Wang <jasowang@redhat.com>
 S:     Maintained
 W:     http://vtun.sourceforge.net/tun
 F:     Documentation/networking/tuntap.rst
 F:     arch/um/os-Linux/drivers/
+F:     drivers/net/tap.c
+F:     drivers/net/tun.c
 
 TURBOCHANNEL SUBSYSTEM
 M:     "Maciej W. Rozycki" <macro@orcam.me.uk>
@@ -21908,9 +21896,8 @@ S:      Maintained
 F:     drivers/usb/misc/apple-mfi-fastcharge.c
 
 USB AR5523 WIRELESS DRIVER
-M:     Pontus Fuchs <pontus.fuchs@gmail.com>
 L:     linux-wireless@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/ath/ar5523/
 
 USB ATTACHED SCSI
@@ -22187,9 +22174,8 @@ F:      drivers/usb/gadget/legacy/webcam.c
 F:     include/uapi/linux/usb/g_uvc.h
 
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
-M:     Jussi Kivilinna <jussi.kivilinna@iki.fi>
 L:     linux-wireless@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/legacy/rndis_wlan.c
 
 USB XHCI DRIVER
@@ -22478,7 +22464,6 @@ L:      virtualization@lists.linux-foundation.org
 S:     Maintained
 F:     drivers/block/virtio_blk.c
 F:     drivers/scsi/virtio_scsi.c
-F:     drivers/vhost/scsi.c
 F:     include/uapi/linux/virtio_blk.h
 F:     include/uapi/linux/virtio_scsi.h
 
@@ -22577,6 +22562,16 @@ F:     include/linux/vhost_iotlb.h
 F:     include/uapi/linux/vhost.h
 F:     kernel/vhost_task.c
 
+VIRTIO HOST (VHOST-SCSI)
+M:     "Michael S. Tsirkin" <mst@redhat.com>
+M:     Jason Wang <jasowang@redhat.com>
+M:     Mike Christie <michael.christie@oracle.com>
+R:     Paolo Bonzini <pbonzini@redhat.com>
+R:     Stefan Hajnoczi <stefanha@redhat.com>
+L:     virtualization@lists.linux-foundation.org
+S:     Maintained
+F:     drivers/vhost/scsi.c
+
 VIRTIO I2C DRIVER
 M:     Conghui Chen <conghui.chen@intel.com>
 M:     Viresh Kumar <viresh.kumar@linaro.org>
@@ -22964,7 +22959,7 @@ F:      drivers/input/misc/wistron_btns.c
 
 WL3501 WIRELESS PCMCIA CARD DRIVER
 L:     linux-wireless@vger.kernel.org
-S:     Odd fixes
+S:     Orphan
 F:     drivers/net/wireless/legacy/wl3501*
 
 WMI BINARY MOF DRIVER
@@ -23535,11 +23530,8 @@ S:     Maintained
 F:     mm/zbud.c
 
 ZD1211RW WIRELESS DRIVER
-M:     Ulrich Kunitz <kune@deine-taler.de>
 L:     linux-wireless@vger.kernel.org
-L:     zd1211-devs@lists.sourceforge.net (subscribers-only)
-S:     Maintained
-W:     http://zd1211.ath.cx/wiki/DriverRewrite
+S:     Orphan
 F:     drivers/net/wireless/zydas/zd1211rw/
 
 ZD1301 MEDIA DRIVER
index 653238528aac925ac8a58ca0a239378ef0b245cb..4739c21a63e2e114011bb00fae3bd1ff292b694e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc7
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 714abe494e5fdc5996be1fd46d7b217916678902..55bb1c09fd39d572a514097244d6de5e306b12b6 100644 (file)
@@ -47,12 +47,6 @@ unsigned long __get_wchan(struct task_struct *p);
 
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
-#define ARCH_HAS_SPINLOCK_PREFETCH
-
-#ifndef CONFIG_SMP
-/* Nothing to prefetch. */
-#define spin_lock_prefetch(lock)       do { } while (0)
-#endif
 
 extern inline void prefetch(const void *ptr)  
 { 
@@ -64,11 +58,4 @@ extern inline void prefetchw(const void *ptr)
        __builtin_prefetch(ptr, 1, 3);
 }
 
-#ifdef CONFIG_SMP
-extern inline void spin_lock_prefetch(const void *ptr)  
-{
-       __builtin_prefetch(ptr, 1, 3);
-}
-#endif
-
 #endif /* __ASM_ALPHA_PROCESSOR_H */
index b650ff1cb022eee9865c2890e223067de8e9a309..3d7473531ab12ad239eedc2d399004a4bb544946 100644 (file)
@@ -385,8 +385,7 @@ setup_memory(void *kernel_end)
 #endif /* CONFIG_BLK_DEV_INITRD */
 }
 
-int __init
-page_is_ram(unsigned long pfn)
+int page_is_ram(unsigned long pfn)
 {
        struct memclust_struct * cluster;
        struct memdesc_struct * memdesc;
index 5b52d75bc6bed8d156588ec8b4ceb59967ef073e..d9927d3181dce88ade9eb738c7ba29bb004d1555 100644 (file)
                valid-mask = <0x003fffff>;
        };
 
-       pci: pciv3@62000000 {
+       pci: pci@62000000 {
                compatible = "arm,integrator-ap-pci", "v3,v360epc-pci";
                device_type = "pci";
                #interrupt-cells = <1>;
index 8b53997675e75032fd37583508a984cc060f4098..73d570a172690cf6ec284c85f8f88c2edb9d63dc 100644 (file)
                                status = "disabled";
 
                                uart4: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <13 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart5: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
                                        interrupts = <14 IRQ_TYPE_LEVEL_HIGH 7>;
                                status = "disabled";
 
                                uart11: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <32 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart12: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart6: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <9 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart7: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <10 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart8: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <11 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart0: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <5 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart1: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <6 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart2: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart3: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <8 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart9: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <15 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart10: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <16 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
index bb240e6a3a6f14707307aae5fc66bf4740b78e0d..088bcc38589fb9ab7b88a92c36d0418b907f402b 100644 (file)
                        };
 
                        watchdog: watchdog@90060000 {
-                               compatible = "arm,amba-primecell";
+                               compatible = "arm,primecell";
                                reg = <0x90060000 0x1000>;
                                interrupts = <3>;
                        };
index 103e73176e47d643d77cb37c230261b2a0752d48..1a00d290092ad447d45d5e0cb5117183c4bc3dfe 100644 (file)
        status = "okay";
 };
 
+&cpu0 {
+       /* CPU rated to 800 MHz, not the default 1.2GHz. */
+       operating-points = <
+               /* kHz   uV */
+               166666  850000
+               400000  900000
+               800000  1050000
+       >;
+};
+
 &ecspi1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_ecspi1>;
index 1a599c294ab863e2c160f23a9e59da6b1ed79b66..1ca4d219609f69fa71d3b514b25b1cd82b18f019 100644 (file)
                pinctrl-0 = <&pinctrl_rtc_int>;
                reg = <0x68>;
                interrupt-parent = <&gpio7>;
-               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+               interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
                status = "disabled";
        };
 };
index 2873369a57c02885d8ec4179ae5c2bf900e268c9..3659fd5ecfa620e665edf570dd9d2b8c0f24bc09 100644 (file)
                                reg = <0x020ca000 0x1000>;
                                interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SLL_CLK_USBPHY2>;
-                               phy-reg_3p0-supply = <&reg_3p0>;
+                               phy-3p0-supply = <&reg_3p0>;
                                fsl,anatop = <&anatop>;
                        };
 
index 3a430866655222703d374d5a86fbfb1940db115a..a05069d49cb88603d0992ad195597de29c3b7748 100644 (file)
                                                        reg = <0>;
 
                                                        ldb_from_lcdif1: endpoint {
-                                                               remote-endpoint = <&lcdif1_to_ldb>;
                                                        };
                                                };
 
                                         <&clks IMX6SX_CLK_USDHC1>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
+                               fsl,tuning-start-tap = <20>;
+                               fsl,tuning-step= <2>;
                                status = "disabled";
                        };
 
                                         <&clks IMX6SX_CLK_USDHC2>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
+                               fsl,tuning-start-tap = <20>;
+                               fsl,tuning-step= <2>;
                                status = "disabled";
                        };
 
                                         <&clks IMX6SX_CLK_USDHC3>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
+                               fsl,tuning-start-tap = <20>;
+                               fsl,tuning-step= <2>;
                                status = "disabled";
                        };
 
                                        power-domains = <&pd_disp>;
                                        status = "disabled";
 
-                                       ports {
-                                               port {
-                                                       lcdif1_to_ldb: endpoint {
-                                                               remote-endpoint = <&ldb_from_lcdif1>;
-                                                       };
+                                       port {
+                                               lcdif1_to_ldb: endpoint {
                                                };
                                        };
                                };
index 54026c2c93fac8593140e42517b46edb3b1a476f..6ffb428dc939c25a0db97f6da45b7f477e90af0e 100644 (file)
                                        <&clks IMX7D_USDHC1_ROOT_CLK>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
+                               fsl,tuning-step = <2>;
+                               fsl,tuning-start-tap = <20>;
                                status = "disabled";
                        };
 
                                        <&clks IMX7D_USDHC2_ROOT_CLK>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
+                               fsl,tuning-step = <2>;
+                               fsl,tuning-start-tap = <20>;
                                status = "disabled";
                        };
 
                                        <&clks IMX7D_USDHC3_ROOT_CLK>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
+                               fsl,tuning-step = <2>;
+                               fsl,tuning-start-tap = <20>;
                                status = "disabled";
                        };
 
index b958607c71dcf3096b2f676683cc337dc12a9c9b..96451c8a815ccd996fcf6f6f9c27e78e4ee0d285 100644 (file)
                        /* MDIO */
                        AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
                        AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
+                       /* Added to support GPIO controlled PHY reset */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT_PULLUP, MUX_MODE7)
                >;
        };
 
                        /* MDIO reset value */
                        AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
                        AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       /* Added to support GPIO controlled PHY reset */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        baseboard_eeprom: baseboard_eeprom@50 {
                compatible = "atmel,24c256";
                reg = <0x50>;
+               vcc-supply = <&ldo4_reg>;
 
                #address-cells = <1>;
                #size-cells = <1>;
 
        ethphy0: ethernet-phy@0 {
                reg = <0>;
+               /* Support GPIO reset on revision C3 boards */
+               reset-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+               reset-assert-us = <300>;
+               reset-deassert-us = <6500>;
        };
 };
 
index 20e4cab64d85551cf6290634a99e23d1b9983a21..623167f30ec2ca6c4d4f3fa2cfe4d9347435f602 100644 (file)
@@ -105,5 +105,4 @@ void sharpsl_pm_led(int val);
 #define MAX1111_ACIN_VOLT   6u
 int sharpsl_pm_pxa_read_max1111(int channel);
 
-void corgi_lcd_limit_intensity(int limit);
 #endif
index 1c021cef965fb5b5a99485f00be1d9edb28d45e5..8bc4ea51a0c164f9fa8bbabb98623a96e8820fd4 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/apm-emulation.h>
+#include <linux/spi/corgi_lcd.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
index 8ba450ab559c81ed3807f64b26cab4b2b562229c..61ad965ef3aca5ff97891738ecdb8ab3ab2b1614 100644 (file)
@@ -8,8 +8,8 @@
  */
 
 #include <linux/io.h>
+#include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/of_device.h>
 #include "common.h"
 
 /* register offsets */
index 38ae674f2f02aad7b424687e2d5bd9288d158e49..3037f58057c9f71f095b685c5a66316260fbd9a2 100644 (file)
        status = "okay";
        clock-frequency = <100000>;
        i2c-sda-falling-time-ns = <890>;  /* hcnt */
-       i2c-sdl-falling-time-ns = <890>;  /* lcnt */
+       i2c-scl-falling-time-ns = <890>;  /* lcnt */
 
        pinctrl-names = "default", "gpio";
        pinctrl-0 = <&i2c1_pmx_func>;
index ede99dcc05580ae6a64fb83972f6ef6839a4f5bf..f4cf30bac5574008c4a66cff9d7ce10cb5c6781a 100644 (file)
        status = "okay";
        clock-frequency = <100000>;
        i2c-sda-falling-time-ns = <890>;  /* hcnt */
-       i2c-sdl-falling-time-ns = <890>;  /* lcnt */
+       i2c-scl-falling-time-ns = <890>;  /* lcnt */
 
        adc@14 {
                compatible = "lltc,ltc2497";
diff --git a/arch/arm64/boot/dts/arm/vexpress-v2m-rs1.dtsi b/arch/arm64/boot/dts/arm/vexpress-v2m-rs1.dtsi
deleted file mode 120000 (symlink)
index 68fd0f8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../arm/boot/dts/vexpress-v2m-rs1.dtsi
\ No newline at end of file
index 03e7679217b24d9f09381a437fffdfabf8d167a9..479948f8a4b752e754de73bfe2888b503ad3298c 100644 (file)
 };
 
 &gpio1 {
-       gpio-line-names = "nINT_ETHPHY", "LED_RED", "WDOG_INT", "X_RTC_INT",
+       gpio-line-names = "", "LED_RED", "WDOG_INT", "X_RTC_INT",
                "", "", "", "RESET_ETHPHY",
                "CAN_nINT", "CAN_EN", "nENABLE_FLATLINK", "",
                "USB_OTG_VBUS_EN", "", "LED_GREEN", "LED_BLUE";
index 92616bc4f71f561ba0d34e210d44e0423d4c5b86..847f08537b48ae244f319c5cd3ab33cfc08b02e9 100644 (file)
 };
 
 &gpio1 {
-       gpio-line-names = "nINT_ETHPHY", "", "WDOG_INT", "X_RTC_INT",
+       gpio-line-names = "", "", "WDOG_INT", "X_RTC_INT",
                "", "", "", "RESET_ETHPHY",
                "", "", "nENABLE_FLATLINK";
 };
                                };
                        };
 
-                       reg_vdd_gpu: buck3 {
+                       reg_vdd_vpu: buck3 {
                                regulator-always-on;
                                regulator-boot-on;
                                regulator-max-microvolt = <1000000>;
index 6f26914602c8841c6dc182d1f57986bcc29b844e..07b07dc954fd66aafd11df636d6252a8f27daff7 100644 (file)
        status = "okay";
 };
 
+&disp_blk_ctrl {
+       status = "disabled";
+};
+
 &pgc_mipi {
        status = "disabled";
 };
index 93088fa1c3b9c9948d7477ef804db51fadea395f..d5b7168558124f93253bcb69f7d0cdf890864d4e 100644 (file)
        status = "okay";
 };
 
+&disp_blk_ctrl {
+       status = "disabled";
+};
+
 &pgc_mipi {
        status = "disabled";
 };
index d6b36f04f3dc155e19409cd194c849f12d3b4993..1a647d4072ba0c80c8542e47880e9dc8a391c3c1 100644 (file)
                                compatible = "fsl,imx8mm-mipi-csi2";
                                reg = <0x32e30000 0x1000>;
                                interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
-                               assigned-clocks = <&clk IMX8MM_CLK_CSI1_CORE>,
-                                                 <&clk IMX8MM_CLK_CSI1_PHY_REF>;
-                               assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_1000M>,
-                                                         <&clk IMX8MM_SYS_PLL2_1000M>;
+                               assigned-clocks = <&clk IMX8MM_CLK_CSI1_CORE>;
+                               assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_1000M>;
+
                                clock-frequency = <333000000>;
                                clocks = <&clk IMX8MM_CLK_DISP_APB_ROOT>,
                                         <&clk IMX8MM_CLK_CSI1_ROOT>,
index d3a67109d55b267a16425f1c1efb30ac785fc2d1..b8946edf317bd1b3fa841ac3468003efa0c670a7 100644 (file)
                        MX8MN_IOMUXC_ENET_RXC_ENET1_RGMII_RXC           0x91
                        MX8MN_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL     0x91
                        MX8MN_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL     0x1f
-                       MX8MN_IOMUXC_GPIO1_IO09_GPIO1_IO9               0x19
+                       MX8MN_IOMUXC_GPIO1_IO09_GPIO1_IO9               0x159
                >;
        };
 
index 9869fe7652fcaf75e083d5e5b771de520a44d8e7..aa38dd6dc9ba54b24ae031dcfd5bc386593da6cd 100644 (file)
                                compatible = "fsl,imx8mm-mipi-csi2";
                                reg = <0x32e30000 0x1000>;
                                interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
-                               assigned-clocks = <&clk IMX8MN_CLK_CAMERA_PIXEL>,
-                                                 <&clk IMX8MN_CLK_CSI1_PHY_REF>;
-                               assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_1000M>,
-                                                         <&clk IMX8MN_SYS_PLL2_1000M>;
+                               assigned-clocks = <&clk IMX8MN_CLK_CAMERA_PIXEL>;
+                               assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_1000M>;
                                assigned-clock-rates = <333000000>;
                                clock-frequency = <333000000>;
                                clocks = <&clk IMX8MN_CLK_DISP_APB_ROOT>,
index 1a2d2c04db32949ed810fb43426f721497cb157f..01eec424f7f75242a2492739cbc59fb06c355c77 100644 (file)
                                                                         <&clk IMX8MQ_SYS1_PLL_800M>,
                                                                         <&clk IMX8MQ_VPU_PLL>;
                                                assigned-clock-rates = <600000000>,
-                                                                      <600000000>,
+                                                                      <300000000>,
                                                                       <800000000>,
                                                                       <0>;
                                        };
index 8643612ace8c7b444451bafb03bf52bfda5acfba..1d8dd14b65cfa8ec5ee610194b6001e05979587b 100644 (file)
 
                        anatop: anatop@44480000 {
                                compatible = "fsl,imx93-anatop", "syscon";
-                               reg = <0x44480000 0x10000>;
+                               reg = <0x44480000 0x2000>;
                        };
 
                        adc1: adc@44530000 {
index 9022ad726741cb112a92076d6652930f9b64082f..a9e7b832c18ced5f2067dbfabe79bb00e6cd019e 100644 (file)
                        };
                };
 
-               pm8150l-thermal {
+               pm8150l-pcb-thermal {
                        polling-delay-passive = <0>;
                        polling-delay = <0>;
                        thermal-sensors = <&pm8150l_adc_tm 1>;
index ab767cfa51ff5e4bca344ea04d4e5cf7bd447867..26f5a4e0ffed3631d8f9159613ae7b426ec191ec 100644 (file)
 
                vreg_l4c: ldo4 {
                        regulator-name = "vreg_l4c";
-                       regulator-min-microvolt = <1100000>;
-                       regulator-max-microvolt = <1300000>;
+                       regulator-min-microvolt = <1200000>;
+                       regulator-max-microvolt = <1200000>;
                        regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
                        /*
                         * FIXME: This should have regulator-allow-set-load but
index e25dc2bb52a7e9ddea5cfc21a3b7f12aa8cca880..06df931d8cad30ff92a4ef5bf638beb6b946a0f6 100644 (file)
                                reg = <0 0x0ae94400 0 0x200>,
                                      <0 0x0ae94600 0 0x280>,
                                      <0 0x0ae94a00 0 0x1e0>;
-                               reg-names = "dsi0_phy",
-                                           "dsi0_phy_lane",
+                               reg-names = "dsi_phy",
+                                           "dsi_phy_lane",
                                            "dsi_pll";
 
                                #clock-cells = <1>;
index d3ae185356365d74833e3b2ac60219490d54c83c..be78a933d8eb237cd591195751b4ca555457a578 100644 (file)
                };
 
                osm_l3: interconnect@18321000 {
-                       compatible = "qcom,sc8180x-osm-l3";
+                       compatible = "qcom,sc8180x-osm-l3", "qcom,osm-l3";
                        reg = <0 0x18321000 0 0x1400>;
 
                        clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
index 18c822abdb88fa546f244e176e617305e6d1676f..b46e55bb8bdecf7dc9b48be71aa9acf6a33f32e4 100644 (file)
@@ -56,7 +56,7 @@
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>;
+                                       <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
                        power-domains = <&CPU_PD0>;
                        power-domain-names = "psci";
                        #cooling-cells = <2>;
@@ -85,7 +85,7 @@
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>;
+                                       <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
                        power-domains = <&CPU_PD1>;
                        power-domain-names = "psci";
                        #cooling-cells = <2>;
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>;
+                                       <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
                        power-domains = <&CPU_PD2>;
                        power-domain-names = "psci";
                        #cooling-cells = <2>;
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>;
+                                       <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
                        power-domains = <&CPU_PD3>;
                        power-domain-names = "psci";
                        #cooling-cells = <2>;
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        operating-points-v2 = <&cpu4_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>;
+                                       <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
                        power-domains = <&CPU_PD4>;
                        power-domain-names = "psci";
                        #cooling-cells = <2>;
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        operating-points-v2 = <&cpu4_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>;
+                                       <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
                        power-domains = <&CPU_PD5>;
                        power-domain-names = "psci";
                        #cooling-cells = <2>;
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        operating-points-v2 = <&cpu4_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>;
+                                       <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
                        power-domains = <&CPU_PD6>;
                        power-domain-names = "psci";
                        #cooling-cells = <2>;
                        qcom,freq-domain = <&cpufreq_hw 2>;
                        operating-points-v2 = <&cpu7_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>;
+                                       <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
                        power-domains = <&CPU_PD7>;
                        power-domain-names = "psci";
                        #cooling-cells = <2>;
                        clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
                        clock-names = "xo", "alternate";
 
-                       #interconnect-cells = <2>;
+                       #interconnect-cells = <1>;
                };
 
                cpufreq_hw: cpufreq@18323000 {
index 83ab6de459bc4469c9e1e7ce08ab7be183020daa..1efa07f2caff4ade6e6a05ba0bf698069791f852 100644 (file)
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>;
+                                       <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
                        #cooling-cells = <2>;
                        L2_0: l2-cache {
                                compatible = "cache";
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>;
+                                       <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
                        #cooling-cells = <2>;
                        L2_100: l2-cache {
                                compatible = "cache";
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>;
+                                       <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
                        #cooling-cells = <2>;
                        L2_200: l2-cache {
                                compatible = "cache";
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>;
+                                       <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
                        #cooling-cells = <2>;
                        L2_300: l2-cache {
                                compatible = "cache";
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        operating-points-v2 = <&cpu4_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>;
+                                       <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
                        #cooling-cells = <2>;
                        L2_400: l2-cache {
                                compatible = "cache";
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        operating-points-v2 = <&cpu4_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>;
+                                       <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
                        #cooling-cells = <2>;
                        L2_500: l2-cache {
                                compatible = "cache";
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        operating-points-v2 = <&cpu4_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>;
+                                       <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
                        #cooling-cells = <2>;
                        L2_600: l2-cache {
                                compatible = "cache";
                        qcom,freq-domain = <&cpufreq_hw 2>;
                        operating-points-v2 = <&cpu7_opp_table>;
                        interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
-                                       <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>;
+                                       <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
                        #cooling-cells = <2>;
                        L2_700: l2-cache {
                                compatible = "cache";
                        clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
                        clock-names = "xo", "alternate";
 
-                       #interconnect-cells = <2>;
+                       #interconnect-cells = <1>;
                };
 
                cpufreq_hw: cpufreq@18591000 {
index 88ef478cb5ccb0c137a204ad0e39210710e06c2e..ec451c616f3e4d1028a9be0eb8431ba0a6905027 100644 (file)
                        qcom,controlled-remotely;
                        iommus = <&apps_smmu 0x594 0x0011>,
                                 <&apps_smmu 0x596 0x0011>;
+                       /* FIXME: Probing BAM DMA causes some abort and system hang */
+                       status = "fail";
                };
 
                crypto: crypto@1dfa000 {
                                 <&apps_smmu 0x596 0x0011>;
                        interconnects = <&aggre2_noc MASTER_CRYPTO 0 &mc_virt SLAVE_EBI1 0>;
                        interconnect-names = "memory";
+                       /* FIXME: dependency BAM DMA is disabled */
+                       status = "disabled";
                };
 
                ipa: ipa@1e40000 {
index 232910e07444eec399c520e52aacf8e76a2aa9d5..66f68fc2b24118af11b2b1e5b73eab13652d3cc9 100644 (file)
                                     <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>,
                                     <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>;
                        interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0",
-                                         "tgiv0", "tgie0", "tgif0",
-                                         "tgia1", "tgib1", "tgiv1", "tgiu1",
-                                         "tgia2", "tgib2", "tgiv2", "tgiu2",
+                                         "tciv0", "tgie0", "tgif0",
+                                         "tgia1", "tgib1", "tciv1", "tciu1",
+                                         "tgia2", "tgib2", "tciv2", "tciu2",
                                          "tgia3", "tgib3", "tgic3", "tgid3",
-                                         "tgiv3",
+                                         "tciv3",
                                          "tgia4", "tgib4", "tgic4", "tgid4",
-                                         "tgiv4",
+                                         "tciv4",
                                          "tgiu5", "tgiv5", "tgiw5",
                                          "tgia6", "tgib6", "tgic6", "tgid6",
-                                         "tgiv6",
+                                         "tciv6",
                                          "tgia7", "tgib7", "tgic7", "tgid7",
-                                         "tgiv7",
+                                         "tciv7",
                                          "tgia8", "tgib8", "tgic8", "tgid8",
-                                         "tgiv8", "tgiu8";
+                                         "tciv8", "tciu8";
                        clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>;
                        power-domains = <&cpg>;
                        resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>;
index 2eba3a8a100d0e268c9c73bc4994e4f9435a4c14..1f1d481dc7830de9dcdbad91a0cc48534dcd1708 100644 (file)
                                     <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>,
                                     <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>;
                        interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0",
-                                         "tgiv0", "tgie0", "tgif0",
-                                         "tgia1", "tgib1", "tgiv1", "tgiu1",
-                                         "tgia2", "tgib2", "tgiv2", "tgiu2",
+                                         "tciv0", "tgie0", "tgif0",
+                                         "tgia1", "tgib1", "tciv1", "tciu1",
+                                         "tgia2", "tgib2", "tciv2", "tciu2",
                                          "tgia3", "tgib3", "tgic3", "tgid3",
-                                         "tgiv3",
+                                         "tciv3",
                                          "tgia4", "tgib4", "tgic4", "tgid4",
-                                         "tgiv4",
+                                         "tciv4",
                                          "tgiu5", "tgiv5", "tgiw5",
                                          "tgia6", "tgib6", "tgic6", "tgid6",
-                                         "tgiv6",
+                                         "tciv6",
                                          "tgia7", "tgib7", "tgic7", "tgid7",
-                                         "tgiv7",
+                                         "tciv7",
                                          "tgia8", "tgib8", "tgic8", "tgid8",
-                                         "tgiv8", "tgiu8";
+                                         "tciv8", "tciu8";
                        clocks = <&cpg CPG_MOD R9A07G054_MTU_X_MCK_MTU3>;
                        power-domains = <&cpg>;
                        resets = <&cpg R9A07G054_MTU_X_PRESET_MTU3>;
index 8332c8aaf49be04664c6fa06744070d242b50560..42ce78beb4134d15bdbbe80bcde366ab32b50c11 100644 (file)
                        };
                        power-domain@PX30_PD_MMC_NAND {
                                reg = <PX30_PD_MMC_NAND>;
-                               clocks =  <&cru HCLK_NANDC>,
-                                         <&cru HCLK_EMMC>,
-                                         <&cru HCLK_SDIO>,
-                                         <&cru HCLK_SFC>,
-                                         <&cru SCLK_EMMC>,
-                                         <&cru SCLK_NANDC>,
-                                         <&cru SCLK_SDIO>,
-                                         <&cru SCLK_SFC>;
+                               clocks = <&cru HCLK_NANDC>,
+                                        <&cru HCLK_EMMC>,
+                                        <&cru HCLK_SDIO>,
+                                        <&cru HCLK_SFC>,
+                                        <&cru SCLK_EMMC>,
+                                        <&cru SCLK_NANDC>,
+                                        <&cru SCLK_SDIO>,
+                                        <&cru SCLK_SFC>;
                                pm_qos = <&qos_emmc>, <&qos_nand>,
                                         <&qos_sdio>, <&qos_sfc>;
                                #power-domain-cells = <0>;
index 7ea48167747c62b606a6308b179161638e2411af..9232357f4fec9c77c1ee7b8dca798b3e739f9f71 100644 (file)
                regulator-name = "vdd_core";
                regulator-min-microvolt = <827000>;
                regulator-max-microvolt = <1340000>;
-               regulator-init-microvolt = <1015000>;
                regulator-settling-time-up-us = <250>;
                regulator-always-on;
                regulator-boot-on;
index a71f249ed384e011dd2434fcaebc1308dd036ff9..e9810d2f04071c8aa6af93d513cfa592b8fb293e 100644 (file)
                regulator-name = "vdd_core";
                regulator-min-microvolt = <827000>;
                regulator-max-microvolt = <1340000>;
-               regulator-init-microvolt = <1015000>;
                regulator-settling-time-up-us = <250>;
                regulator-always-on;
                regulator-boot-on;
index d1f343345f67499a737d83b3d791b47efce32deb..6464ef4d113ddd8613910ed24c6809cb016f8c0e 100644 (file)
                compatible = "brcm,bcm4329-fmac";
                reg = <1>;
                interrupt-parent = <&gpio0>;
-               interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>;
+               interrupts = <RK_PA3 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-names = "host-wake";
                pinctrl-names = "default";
                pinctrl-0 = <&wifi_host_wake_l>;
index b6e082f1f6d9791bd910a31227c06004efc87644..7c5f441a2219ee4ec7631a09b5309ff29c5d77f4 100644 (file)
                        vcc_sdio: LDO_REG4 {
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-init-microvolt = <3000000>;
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-name = "vcc_sdio";
index 028eb508ae3026c933cadbe1333a1939c563d225..8bfd5f88d1ef61d9ce45d617d4fc5d199d4b84cc 100644 (file)
 &sdhci {
        max-frequency = <150000000>;
        bus-width = <8>;
-       mmc-hs400-1_8v;
+       mmc-hs200-1_8v;
        non-removable;
-       mmc-hs400-enhanced-strobe;
        status = "okay";
 };
 
index 907071d4fe80445b23a8b6b6a5f36fa382dd65f3..980c4534313a21b48b98fff3caf9cf48ba2c4210 100644 (file)
@@ -45,7 +45,7 @@
        sdio_pwrseq: sdio-pwrseq {
                compatible = "mmc-pwrseq-simple";
                clocks = <&rk808 1>;
-               clock-names = "ext_clock";
+               clock-names = "lpo";
                pinctrl-names = "default";
                pinctrl-0 = <&wifi_enable_h>;
                reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
 };
 
 &sdhci {
+       max-frequency = <150000000>;
        bus-width = <8>;
-       mmc-hs400-1_8v;
-       mmc-hs400-enhanced-strobe;
+       mmc-hs200-1_8v;
        non-removable;
        status = "okay";
 };
index cec3b7b1b94747bbde9221f5021fc04bb562e6dc..8a17c1eaae15ee97dd32b6e442aba625b56622d2 100644 (file)
@@ -31,7 +31,7 @@
                compatible = "brcm,bcm4329-fmac";
                reg = <1>;
                interrupt-parent = <&gpio0>;
-               interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>;
+               interrupts = <RK_PA3 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-names = "host-wake";
                pinctrl-names = "default";
                pinctrl-0 = <&wifi_host_wake_l>;
index a2c31d53b45bc2e09df1a5c627cbf8a8c0449965..8cbf3d9a4f22ee975fe45616c31c71f351597b0b 100644 (file)
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
                                regulator-name = "vdd_logic";
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
                                regulator-name = "vdd_gpu";
                regulator-boot-on;
                regulator-min-microvolt = <712500>;
                regulator-max-microvolt = <1390000>;
-               regulator-init-microvolt = <900000>;
                regulator-name = "vdd_cpu";
                regulator-ramp-delay = <2300>;
                vin-supply = <&vcc_sys>;
index 410cd3e5e7bca445c903006e3901e1dc22c55ead..0c18406e4c597333cd4ee1daa50dab3c3b2308ea 100644 (file)
 
 &gmac1 {
        assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
-       assigned-clock-parents =  <&cru SCLK_GMAC1_RGMII_SPEED>, <&gmac1_clkin>;
+       assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&gmac1_clkin>;
        phy-mode = "rgmii";
        clock_in_out = "input";
        pinctrl-names = "default";
                compatible = "brcm,bcm4329-fmac";
                reg = <1>;
                interrupt-parent = <&gpio2>;
-               interrupts = <RK_PB2 GPIO_ACTIVE_HIGH>;
+               interrupts = <RK_PB2 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-names = "host-wake";
                pinctrl-names = "default";
                pinctrl-0 = <&wifi_host_wake_h>;
index ff936b71357975e767d36da0ceda3b1f88071e33..1c6d83b47cd217b53b6a65a5f520e7dac858c613 100644 (file)
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
 
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
 
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
 
index 8d61f824c12dc8cdb5627ec3344ee8708a3666ca..d899087bf0b559ff9a7110376409615f1cfebe0b 100644 (file)
                                regulator-always-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
 
                                regulator-name = "vdd_gpu_npu";
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
 
index 25a8c781f4e755fda3b7364ae514359a3cad422d..854d02b46e6fcd72144b57a30079513767a07180 100644 (file)
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
                                regulator-name = "vdd_logic";
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
                                regulator-name = "vdd_gpu";
index b276eb0810c70e692a6a3b6792480d77a8e618a4..2d92713be2a09f97ca603cbb64bdc49fd4fc00db 100644 (file)
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
 
                                regulator-state-mem {
                                regulator-boot-on;
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
 
                                regulator-state-mem {
index 5e4236af4fcb8ee34da816017ccd591f3b0826b1..1b1c67d5b1ef335ed546ec7bea07b8a611da83e9 100644 (file)
 
 &mdio1 {
        rgmii_phy1: ethernet-phy@0 {
-               compatible="ethernet-phy-ieee802.3-c22";
-               reg= <0x0>;
+               compatible = "ethernet-phy-ieee802.3-c22";
+               reg = <0x0>;
        };
 };
 
index 42889c5900bd5b740937a151e7d0772632de96f9..938092fce18661f354294c815683923a8888dbfd 100644 (file)
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
 
                                regulator-state-mem {
                                regulator-name = "vdd_gpu";
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
 
                                regulator-state-mem {
index 31aa2b8efe39314087190027c495cb2b4a26c163..63bae36b8f7e7d621b8961182e5a799bd5d05f5a 100644 (file)
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
                                regulator-state-mem {
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
                                        regulator-state-mem {
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-name = "vdd_npu";
                                regulator-state-mem {
index ff0bf24cc1a2a67adaf20fa6d91e54d879d4fa86..f9127ddfbb7dfdaa9b2bfd6040ef9ed2ab1986b3 100644 (file)
                                regulator-name = "vdd_logic";
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
                        vdd_gpu: DCDC_REG2 {
                                regulator-name = "vdd_gpu";
                                regulator-always-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
 
                        vdd_npu: DCDC_REG4 {
                                regulator-name = "vdd_npu";
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
index 674792567fa6e288c94169406cd69b0e2262d5b2..19f8fc369b1308cdfe8bfaa3b49e6f6b5134bb27 100644 (file)
                                regulator-name = "vdd_logic";
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
                        vdd_gpu: DCDC_REG2 {
                                regulator-name = "vdd_gpu";
                                regulator-always-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
 
                        vdd_npu: DCDC_REG4 {
                                regulator-name = "vdd_npu";
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
index 25e205632a686ddaa589b0542e69888242e8c4ac..89e84e3a92629a877a5a085c9ea5d1b46889e60a 100644 (file)
                                regulator-name = "vdd_logic";
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
                        vdd_gpu: DCDC_REG2 {
                                regulator-name = "vdd_gpu";
                                regulator-always-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
 
                        vdd_npu: DCDC_REG4 {
                                regulator-name = "vdd_npu";
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
 
                        vcca1v8_image: LDO_REG9 {
                                regulator-name = "vcca1v8_image";
-                               regulator-init-microvolt = <950000>;
                                regulator-min-microvolt = <950000>;
                                regulator-max-microvolt = <1800000>;
 
index e653b067aa5d983d73c9965bdf8c475a97cfd10e..a8a4cc190eb32e2cf18d9ab7f8549a96c12a6465 100644 (file)
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
 
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
 
                                regulator-boot-on;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
-                               regulator-init-microvolt = <900000>;
                                regulator-ramp-delay = <6001>;
                                regulator-initial-mode = <0x2>;
 
index 58ba328ea782476ce01b4377b197870017806068..93189f830640066a3f979fb6b84a36f67b9ffbd5 100644 (file)
                                regulator-name = "vdd_logic";
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
                        vdd_gpu: DCDC_REG2 {
                                regulator-name = "vdd_gpu";
                                regulator-always-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
 
                        vdd_npu: DCDC_REG4 {
                                regulator-name = "vdd_npu";
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
index 59ecf868dbd0e5f2e201a653aee6ae3054bd4a1b..a337f547caf538105a6e1644466ba62af44bc395 100644 (file)
                                regulator-name = "vdd_logic";
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
                        vdd_gpu: DCDC_REG2 {
                                regulator-name = "vdd_gpu";
                                regulator-always-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
 
                        vdd_npu: DCDC_REG4 {
                                regulator-name = "vdd_npu";
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
index c50fbdd48680ca7273fdcd53f7fef527d8e1c008..45b03dcbbad455d5c02d62bbbd09eb1d5f2e4e2f 100644 (file)
                                regulator-name = "vdd_logic";
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
                        vdd_gpu: DCDC_REG2 {
                                regulator-name = "vdd_gpu";
                                regulator-always-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
 
                        vdd_npu: DCDC_REG4 {
                                regulator-name = "vdd_npu";
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
index 917f5b2b8aab828662a871d03ad4fd8707db670f..e05ab11981f554ae6315267b3557b427b721bde8 100644 (file)
                                regulator-name = "vdd_logic";
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
                        vdd_gpu: DCDC_REG2 {
                                regulator-name = "vdd_gpu";
                                regulator-always-on;
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
 
                        vdd_npu: DCDC_REG4 {
                                regulator-name = "vdd_npu";
-                               regulator-init-microvolt = <900000>;
                                regulator-initial-mode = <0x2>;
                                regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <1350000>;
index afda976680bca7b60169cf8140f07f2d41218008..51537030f8e39e28ee6cef956fce4fbbbcfcaf6d 100644 (file)
                                regulator-boot-on;
                                regulator-min-microvolt = <550000>;
                                regulator-max-microvolt = <950000>;
-                               regulator-init-microvolt = <750000>;
                                regulator-ramp-delay = <12500>;
                                regulator-name = "vdd_vdenc_s0";
 
index 4d9ed2a0273637a32b22ad04a65e81ae34986a89..1a60a275ddf9b47bb2454faa3b47f63f1a709a1b 100644 (file)
        cpu-supply = <&vdd_cpu_lit_s0>;
 };
 
-&cpu_b0{
+&cpu_b0 {
        cpu-supply = <&vdd_cpu_big0_s0>;
 };
 
-&cpu_b1{
+&cpu_b1 {
        cpu-supply = <&vdd_cpu_big0_s0>;
 };
 
-&cpu_b2{
+&cpu_b2 {
        cpu-supply = <&vdd_cpu_big1_s0>;
 };
 
-&cpu_b3{
+&cpu_b3 {
        cpu-supply = <&vdd_cpu_big1_s0>;
 };
 
index 8e5ffb58f83ea56d634e791521025ec744e0fa16..b7afaa026842b7ebce94228e6031ce99f5cbb2a8 100644 (file)
 .Lskip_hcrx_\@:
 .endm
 
+/* Check if running in host at EL2 mode, i.e., (h)VHE. Jump to fail if not. */
+.macro __check_hvhe fail, tmp
+       mrs     \tmp, hcr_el2
+       and     \tmp, \tmp, #HCR_E2H
+       cbz     \tmp, \fail
+.endm
+
 /*
  * Allow Non-secure EL1 and EL0 to access physical timer and counter.
  * This is not necessary for VHE, since the host kernel runs in EL2,
@@ -43,9 +50,7 @@
  */
 .macro __init_el2_timers
        mov     x0, #3                          // Enable EL1 physical timers
-       mrs     x1, hcr_el2
-       and     x1, x1, #HCR_E2H
-       cbz     x1, .LnVHE_\@
+       __check_hvhe .LnVHE_\@, x1
        lsl     x0, x0, #10
 .LnVHE_\@:
        msr     cnthctl_el2, x0
 
 /* Coprocessor traps */
 .macro __init_el2_cptr
-       mrs     x1, hcr_el2
-       and     x1, x1, #HCR_E2H
-       cbz     x1, .LnVHE_\@
+       __check_hvhe .LnVHE_\@, x1
        mov     x0, #(CPACR_EL1_FPEN_EL1EN | CPACR_EL1_FPEN_EL0EN)
-       b       .Lset_cptr_\@
+       msr     cpacr_el1, x0
+       b       .Lskip_set_cptr_\@
 .LnVHE_\@:
        mov     x0, #0x33ff
-.Lset_cptr_\@:
        msr     cptr_el2, x0                    // Disable copro. traps to EL2
+.Lskip_set_cptr_\@:
 .endm
 
 /* Disable any fine grained traps */
        check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2
 
 .Linit_sve_\@: /* SVE register access */
-       mrs     x0, cptr_el2                    // Disable SVE traps
-       mrs     x1, hcr_el2
-       and     x1, x1, #HCR_E2H
-       cbz     x1, .Lcptr_nvhe_\@
+       __check_hvhe .Lcptr_nvhe_\@, x1
 
-       // VHE case
+       // (h)VHE case
+       mrs     x0, cpacr_el1                   // Disable SVE traps
        orr     x0, x0, #(CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN)
-       b       .Lset_cptr_\@
+       msr     cpacr_el1, x0
+       b       .Lskip_set_cptr_\@
 
 .Lcptr_nvhe_\@: // nVHE case
+       mrs     x0, cptr_el2                    // Disable SVE traps
        bic     x0, x0, #CPTR_EL2_TZ
-.Lset_cptr_\@:
        msr     cptr_el2, x0
+.Lskip_set_cptr_\@:
        isb
        mov     x1, #ZCR_ELx_LEN_MASK           // SVE: Enable full vector
        msr_s   SYS_ZCR_EL2, x1                 // length for EL1.
        check_override id_aa64pfr1, ID_AA64PFR1_EL1_SME_SHIFT, .Linit_sme_\@, .Lskip_sme_\@, x1, x2
 
 .Linit_sme_\@: /* SME register access and priority mapping */
+       __check_hvhe .Lcptr_nvhe_sme_\@, x1
+
+       // (h)VHE case
+       mrs     x0, cpacr_el1                   // Disable SME traps
+       orr     x0, x0, #(CPACR_EL1_SMEN_EL0EN | CPACR_EL1_SMEN_EL1EN)
+       msr     cpacr_el1, x0
+       b       .Lskip_set_cptr_sme_\@
+
+.Lcptr_nvhe_sme_\@: // nVHE case
        mrs     x0, cptr_el2                    // Disable SME traps
        bic     x0, x0, #CPTR_EL2_TSM
        msr     cptr_el2, x0
+.Lskip_set_cptr_sme_\@:
        isb
 
        mrs     x1, sctlr_el2
index 67f2fb781f59e8ad3fdc5dc6fe9e692a1fbd27d2..8df46f186c64b8e2665a99a5982ee1f5f65c7a4d 100644 (file)
@@ -356,7 +356,7 @@ static inline int sme_max_virtualisable_vl(void)
        return vec_max_virtualisable_vl(ARM64_VEC_SME);
 }
 
-extern void sme_alloc(struct task_struct *task);
+extern void sme_alloc(struct task_struct *task, bool flush);
 extern unsigned int sme_get_vl(void);
 extern int sme_set_current_vl(unsigned long arg);
 extern int sme_get_current_vl(void);
@@ -388,7 +388,7 @@ static inline void sme_smstart_sm(void) { }
 static inline void sme_smstop_sm(void) { }
 static inline void sme_smstop(void) { }
 
-static inline void sme_alloc(struct task_struct *task) { }
+static inline void sme_alloc(struct task_struct *task, bool flush) { }
 static inline void sme_setup(void) { }
 static inline unsigned int sme_get_vl(void) { return 0; }
 static inline int sme_max_vl(void) { return 0; }
index 7d170aaa2db4195b5405a46caf6bcbcb22f0fe38..24e28bb2d95b609dfb5ef3e25ffdadb4e12251fe 100644 (file)
@@ -278,7 +278,7 @@ asmlinkage void __noreturn hyp_panic_bad_stack(void);
 asmlinkage void kvm_unexpected_el2_exception(void);
 struct kvm_cpu_context;
 void handle_trap(struct kvm_cpu_context *host_ctxt);
-asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on);
+asmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on);
 void __noreturn __pkvm_init_finalise(void);
 void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 void kvm_patch_vector_branch(struct alt_instr *alt,
index efc0b45d79c36083ba1b4ca0ace283cee983ec4c..3d6725ff0bf6d24577c84c6814fcc814b0681fb8 100644 (file)
@@ -571,6 +571,14 @@ static inline bool vcpu_has_feature(struct kvm_vcpu *vcpu, int feature)
        return test_bit(feature, vcpu->arch.features);
 }
 
+static __always_inline void kvm_write_cptr_el2(u64 val)
+{
+       if (has_vhe() || has_hvhe())
+               write_sysreg(val, cpacr_el1);
+       else
+               write_sysreg(val, cptr_el2);
+}
+
 static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu)
 {
        u64 val;
@@ -578,8 +586,16 @@ static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu)
        if (has_vhe()) {
                val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN |
                       CPACR_EL1_ZEN_EL1EN);
+               if (cpus_have_final_cap(ARM64_SME))
+                       val |= CPACR_EL1_SMEN_EL1EN;
        } else if (has_hvhe()) {
                val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN);
+
+               if (!vcpu_has_sve(vcpu) ||
+                   (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED))
+                       val |= CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN;
+               if (cpus_have_final_cap(ARM64_SME))
+                       val |= CPACR_EL1_SMEN_EL1EN | CPACR_EL1_SMEN_EL0EN;
        } else {
                val = CPTR_NVHE_EL2_RES1;
 
@@ -597,9 +613,6 @@ static __always_inline void kvm_reset_cptr_el2(struct kvm_vcpu *vcpu)
 {
        u64 val = kvm_get_reset_cptr_el2(vcpu);
 
-       if (has_vhe() || has_hvhe())
-               write_sysreg(val, cpacr_el1);
-       else
-               write_sysreg(val, cptr_el2);
+       kvm_write_cptr_el2(val);
 }
 #endif /* __ARM64_KVM_EMULATE_H__ */
index 3918f2a679707464ee35190cbef92aa4ee8866d7..e5bc54522e7112772e294b7cc0e34a01948f741f 100644 (file)
@@ -359,14 +359,6 @@ static inline void prefetchw(const void *ptr)
        asm volatile("prfm pstl1keep, %a0\n" : : "p" (ptr));
 }
 
-#define ARCH_HAS_SPINLOCK_PREFETCH
-static inline void spin_lock_prefetch(const void *ptr)
-{
-       asm volatile(ARM64_LSE_ATOMIC_INSN(
-                    "prfm pstl1strm, %a0",
-                    "nop") : : "p" (ptr));
-}
-
 extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */
 extern void __init minsigstksz_setup(void);
 
diff --git a/arch/arm64/include/uapi/asm/bitsperlong.h b/arch/arm64/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..485d60b
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_BITSPERLONG_H
+#define __ASM_BITSPERLONG_H
+
+#define __BITS_PER_LONG 64
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_BITSPERLONG_H */
index 520b681a07bb0987ef595b7d0bbb795b7b8911ec..087c05aa960ea310e3be7a4d5f3db06ecf11eeb9 100644 (file)
@@ -679,7 +679,7 @@ static void fpsimd_to_sve(struct task_struct *task)
        void *sst = task->thread.sve_state;
        struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state;
 
-       if (!system_supports_sve())
+       if (!system_supports_sve() && !system_supports_sme())
                return;
 
        vq = sve_vq_from_vl(thread_get_cur_vl(&task->thread));
@@ -705,7 +705,7 @@ static void sve_to_fpsimd(struct task_struct *task)
        unsigned int i;
        __uint128_t const *p;
 
-       if (!system_supports_sve())
+       if (!system_supports_sve() && !system_supports_sme())
                return;
 
        vl = thread_get_cur_vl(&task->thread);
@@ -835,7 +835,8 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
        void *sst = task->thread.sve_state;
        struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state;
 
-       if (!test_tsk_thread_flag(task, TIF_SVE))
+       if (!test_tsk_thread_flag(task, TIF_SVE) &&
+           !thread_sm_enabled(&task->thread))
                return;
 
        vq = sve_vq_from_vl(thread_get_cur_vl(&task->thread));
@@ -909,7 +910,7 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,
                         */
                        task->thread.svcr &= ~(SVCR_SM_MASK |
                                               SVCR_ZA_MASK);
-                       clear_thread_flag(TIF_SME);
+                       clear_tsk_thread_flag(task, TIF_SME);
                        free_sme = true;
                }
        }
@@ -1284,9 +1285,9 @@ void fpsimd_release_task(struct task_struct *dead_task)
  * the interest of testability and predictability, the architecture
  * guarantees that when ZA is enabled it will be zeroed.
  */
-void sme_alloc(struct task_struct *task)
+void sme_alloc(struct task_struct *task, bool flush)
 {
-       if (task->thread.sme_state) {
+       if (task->thread.sme_state && flush) {
                memset(task->thread.sme_state, 0, sme_state_size(task));
                return;
        }
@@ -1514,7 +1515,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
        }
 
        sve_alloc(current, false);
-       sme_alloc(current);
+       sme_alloc(current, true);
        if (!current->thread.sve_state || !current->thread.sme_state) {
                force_sig(SIGKILL);
                return;
index d7f4f0d1ae120248b0a483c71245fb991b4925d2..187aa2b175b4f68abd9a81ca84e653a975fa7743 100644 (file)
@@ -881,6 +881,13 @@ static int sve_set_common(struct task_struct *target,
                        break;
                case ARM64_VEC_SME:
                        target->thread.svcr |= SVCR_SM_MASK;
+
+                       /*
+                        * Disable traps and ensure there is SME storage but
+                        * preserve any currently set values in ZA/ZT.
+                        */
+                       sme_alloc(target, false);
+                       set_tsk_thread_flag(target, TIF_SME);
                        break;
                default:
                        WARN_ON_ONCE(1);
@@ -932,11 +939,13 @@ static int sve_set_common(struct task_struct *target,
        /*
         * Ensure target->thread.sve_state is up to date with target's
         * FPSIMD regs, so that a short copyin leaves trailing
-        * registers unmodified.  Always enable SVE even if going into
-        * streaming mode.
+        * registers unmodified.  Only enable SVE if we are
+        * configuring normal SVE, a system with streaming SVE may not
+        * have normal SVE.
         */
        fpsimd_sync_to_sve(target);
-       set_tsk_thread_flag(target, TIF_SVE);
+       if (type == ARM64_VEC_SVE)
+               set_tsk_thread_flag(target, TIF_SVE);
        target->thread.fp_type = FP_STATE_SVE;
 
        BUILD_BUG_ON(SVE_PT_SVE_OFFSET != sizeof(header));
@@ -1098,7 +1107,7 @@ static int za_set(struct task_struct *target,
        }
 
        /* Allocate/reinit ZA storage */
-       sme_alloc(target);
+       sme_alloc(target, true);
        if (!target->thread.sme_state) {
                ret = -ENOMEM;
                goto out;
@@ -1168,8 +1177,13 @@ static int zt_set(struct task_struct *target,
        if (!system_supports_sme2())
                return -EINVAL;
 
+       /* Ensure SVE storage in case this is first use of SME */
+       sve_alloc(target, false);
+       if (!target->thread.sve_state)
+               return -ENOMEM;
+
        if (!thread_za_enabled(&target->thread)) {
-               sme_alloc(target);
+               sme_alloc(target, true);
                if (!target->thread.sme_state)
                        return -ENOMEM;
        }
@@ -1177,8 +1191,12 @@ static int zt_set(struct task_struct *target,
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                 thread_zt_state(&target->thread),
                                 0, ZT_SIG_REG_BYTES);
-       if (ret == 0)
+       if (ret == 0) {
                target->thread.svcr |= SVCR_ZA_MASK;
+               set_tsk_thread_flag(target, TIF_SME);
+       }
+
+       fpsimd_flush_task_state(target);
 
        return ret;
 }
index e304f7ebec2a91ff88c83afa20d8722a61f99cfa..c7ebe744c64e39fb93f6b26433beb460f6aed079 100644 (file)
@@ -475,7 +475,7 @@ static int restore_za_context(struct user_ctxs *user)
        fpsimd_flush_task_state(current);
        /* From now, fpsimd_thread_switch() won't touch thread.sve_state */
 
-       sme_alloc(current);
+       sme_alloc(current, true);
        if (!current->thread.sme_state) {
                current->thread.svcr &= ~SVCR_ZA_MASK;
                clear_thread_flag(TIF_SME);
index 72dc53a75d1c8b09b512f11d06fee248dbe991d3..d1cb298a58a084c825d3ad13f2837da3afd0ba2e 100644 (file)
@@ -55,7 +55,7 @@ DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
 
 static bool vgic_present, kvm_arm_initialised;
 
-static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled);
+static DEFINE_PER_CPU(unsigned char, kvm_hyp_initialized);
 DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
 bool is_kvm_arm_initialised(void)
@@ -1864,18 +1864,24 @@ static void cpu_hyp_reinit(void)
        cpu_hyp_init_features();
 }
 
-static void _kvm_arch_hardware_enable(void *discard)
+static void cpu_hyp_init(void *discard)
 {
-       if (!__this_cpu_read(kvm_arm_hardware_enabled)) {
+       if (!__this_cpu_read(kvm_hyp_initialized)) {
                cpu_hyp_reinit();
-               __this_cpu_write(kvm_arm_hardware_enabled, 1);
+               __this_cpu_write(kvm_hyp_initialized, 1);
        }
 }
 
-int kvm_arch_hardware_enable(void)
+static void cpu_hyp_uninit(void *discard)
 {
-       int was_enabled;
+       if (__this_cpu_read(kvm_hyp_initialized)) {
+               cpu_hyp_reset();
+               __this_cpu_write(kvm_hyp_initialized, 0);
+       }
+}
 
+int kvm_arch_hardware_enable(void)
+{
        /*
         * Most calls to this function are made with migration
         * disabled, but not with preemption disabled. The former is
@@ -1884,36 +1890,23 @@ int kvm_arch_hardware_enable(void)
         */
        preempt_disable();
 
-       was_enabled = __this_cpu_read(kvm_arm_hardware_enabled);
-       _kvm_arch_hardware_enable(NULL);
+       cpu_hyp_init(NULL);
 
-       if (!was_enabled) {
-               kvm_vgic_cpu_up();
-               kvm_timer_cpu_up();
-       }
+       kvm_vgic_cpu_up();
+       kvm_timer_cpu_up();
 
        preempt_enable();
 
        return 0;
 }
 
-static void _kvm_arch_hardware_disable(void *discard)
-{
-       if (__this_cpu_read(kvm_arm_hardware_enabled)) {
-               cpu_hyp_reset();
-               __this_cpu_write(kvm_arm_hardware_enabled, 0);
-       }
-}
-
 void kvm_arch_hardware_disable(void)
 {
-       if (__this_cpu_read(kvm_arm_hardware_enabled)) {
-               kvm_timer_cpu_down();
-               kvm_vgic_cpu_down();
-       }
+       kvm_timer_cpu_down();
+       kvm_vgic_cpu_down();
 
        if (!is_protected_kvm_enabled())
-               _kvm_arch_hardware_disable(NULL);
+               cpu_hyp_uninit(NULL);
 }
 
 #ifdef CONFIG_CPU_PM
@@ -1922,16 +1915,16 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
                                    void *v)
 {
        /*
-        * kvm_arm_hardware_enabled is left with its old value over
+        * kvm_hyp_initialized is left with its old value over
         * PM_ENTER->PM_EXIT. It is used to indicate PM_EXIT should
         * re-enable hyp.
         */
        switch (cmd) {
        case CPU_PM_ENTER:
-               if (__this_cpu_read(kvm_arm_hardware_enabled))
+               if (__this_cpu_read(kvm_hyp_initialized))
                        /*
-                        * don't update kvm_arm_hardware_enabled here
-                        * so that the hardware will be re-enabled
+                        * don't update kvm_hyp_initialized here
+                        * so that the hyp will be re-enabled
                         * when we resume. See below.
                         */
                        cpu_hyp_reset();
@@ -1939,8 +1932,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
                return NOTIFY_OK;
        case CPU_PM_ENTER_FAILED:
        case CPU_PM_EXIT:
-               if (__this_cpu_read(kvm_arm_hardware_enabled))
-                       /* The hardware was enabled before suspend. */
+               if (__this_cpu_read(kvm_hyp_initialized))
+                       /* The hyp was enabled before suspend. */
                        cpu_hyp_reinit();
 
                return NOTIFY_OK;
@@ -2021,7 +2014,7 @@ static int __init init_subsystems(void)
        /*
         * Enable hardware so that subsystem initialisation can access EL2.
         */
-       on_each_cpu(_kvm_arch_hardware_enable, NULL, 1);
+       on_each_cpu(cpu_hyp_init, NULL, 1);
 
        /*
         * Register CPU lower-power notifier
@@ -2059,7 +2052,7 @@ out:
                hyp_cpu_pm_exit();
 
        if (err || !is_protected_kvm_enabled())
-               on_each_cpu(_kvm_arch_hardware_disable, NULL, 1);
+               on_each_cpu(cpu_hyp_uninit, NULL, 1);
 
        return err;
 }
@@ -2097,7 +2090,7 @@ static int __init do_pkvm_init(u32 hyp_va_bits)
         * The stub hypercalls are now disabled, so set our local flag to
         * prevent a later re-init attempt in kvm_arch_hardware_enable().
         */
-       __this_cpu_write(kvm_arm_hardware_enabled, 1);
+       __this_cpu_write(kvm_hyp_initialized, 1);
        preempt_enable();
 
        return ret;
index 4bddb8541bece001f45c3669a79b631441dcd7f3..34f222af61652bc05b8deaf1fa315a8ad42e9562 100644 (file)
@@ -457,6 +457,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu)
         */
        val &= ~(TCR_HD | TCR_HA);
        write_sysreg_el1(val, SYS_TCR);
+       __kvm_skip_instr(vcpu);
        return true;
 }
 
index 58dcd92bf346e15653cf64931c274888aef9607d..ab4f5d160c58f9969f4820a479dbf3d119b2d617 100644 (file)
@@ -705,7 +705,20 @@ int hyp_ffa_init(void *pages)
        if (res.a0 == FFA_RET_NOT_SUPPORTED)
                return 0;
 
-       if (res.a0 != FFA_VERSION_1_0)
+       /*
+        * Firmware returns the maximum supported version of the FF-A
+        * implementation. Check that the returned version is
+        * backwards-compatible with the hyp according to the rules in DEN0077A
+        * v1.1 REL0 13.2.1.
+        *
+        * Of course, things are never simple when dealing with firmware. v1.1
+        * broke ABI with v1.0 on several structures, which is itself
+        * incompatible with the aforementioned versioning scheme. The
+        * expectation is that v1.x implementations that do not support the v1.0
+        * ABI return NOT_SUPPORTED rather than a version number, according to
+        * DEN0077A v1.1 REL0 18.6.4.
+        */
+       if (FFA_MAJOR_VERSION(res.a0) != 1)
                return -EOPNOTSUPP;
 
        arm_smccc_1_1_smc(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0, &res);
index 0a6271052def0a9c2198d2578c3993ba2b606b81..e89a23153e85e13a888a0d592c6691be23885e9a 100644 (file)
@@ -63,7 +63,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
                __activate_traps_fpsimd32(vcpu);
        }
 
-       write_sysreg(val, cptr_el2);
+       kvm_write_cptr_el2(val);
        write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
        if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
index 87927eb824ccd9ed2f14d83434a2fb2ec793aaee..58500a964238b05edb391417be33081c8c529c33 100644 (file)
@@ -11,7 +11,7 @@
 
 #ifdef __KERNEL__
 
-#include <acpi/pdc_intel.h>
+#include <acpi/proc_cap_intel.h>
 
 #include <linux/init.h>
 #include <linux/numa.h>
@@ -69,9 +69,9 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
 #endif
 
 static inline bool arch_has_acpi_pdc(void) { return true; }
-static inline void arch_acpi_set_pdc_bits(u32 *buf)
+static inline void arch_acpi_set_proc_cap_bits(u32 *cap)
 {
-       buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
+       *cap |= ACPI_PROC_CAP_EST_CAPABILITY_SMP;
 }
 
 #ifdef CONFIG_ACPI_NUMA
index d1978e0040548fbacd2f63bb7aca1bbf08068d66..47e3801b526a11c28269505a84fafa47d590a1a4 100644 (file)
@@ -634,7 +634,6 @@ ia64_imva (void *addr)
 
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
-#define ARCH_HAS_SPINLOCK_PREFETCH
 #define PREFETCH_STRIDE                        L1_CACHE_BYTES
 
 static inline void
@@ -649,8 +648,6 @@ prefetchw (const void *x)
        ia64_lfetch_excl(ia64_lfhint_none, x);
 }
 
-#define spin_lock_prefetch(x)  prefetchw(x)
-
 extern unsigned long boot_option_idle_override;
 
 enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT,
index 9151dcd9d0d5c6c43d01f9b51b2c88264e4636dc..af9cea21c8535a568c502e141fe130de285b3ea2 100644 (file)
@@ -58,8 +58,6 @@
 
 #define cpu_has_rixi           (cpu_data[0].cputype != CPU_CAVIUM_OCTEON)
 
-#define ARCH_HAS_SPINLOCK_PREFETCH 1
-#define spin_lock_prefetch(x) prefetch(x)
 #define PREFETCH_STRIDE 128
 
 #ifdef __OCTEON__
index 1401e4c5fe5f7ab1c6d77f9e033e9bbe1749b9b3..bf2b21b96f0bf1ae19d93b9413294440423261c9 100644 (file)
@@ -2,7 +2,7 @@
 #
 config LIGHTWEIGHT_SPINLOCK_CHECK
        bool "Enable lightweight spinlock checks"
-       depends on SMP && !DEBUG_SPINLOCK
+       depends on DEBUG_KERNEL && SMP && !DEBUG_SPINLOCK
        default y
        help
          Add checks with low performance impact to the spinlock functions
index 7ee49f5881d15858cbad514d5b063ae39fb5ab77..d389359e22ac6c168538b02a3c55fb04cfa59760 100644 (file)
@@ -117,7 +117,7 @@ char *strchr(const char *s, int c)
        return NULL;
 }
 
-int puts(const char *s)
+static int puts(const char *s)
 {
        const char *nuline = s;
 
@@ -172,7 +172,7 @@ static int print_num(unsigned long num, int base)
        return 0;
 }
 
-int printf(const char *fmt, ...)
+static int printf(const char *fmt, ...)
 {
        va_list args;
        int i = 0;
@@ -204,13 +204,13 @@ void abort(void)
 }
 
 #undef malloc
-void *malloc(size_t size)
+static void *malloc(size_t size)
 {
        return malloc_gzip(size);
 }
 
 #undef free
-void free(void *ptr)
+static void free(void *ptr)
 {
        return free_gzip(ptr);
 }
@@ -278,7 +278,7 @@ static void parse_elf(void *output)
        free(phdrs);
 }
 
-unsigned long decompress_kernel(unsigned int started_wide,
+asmlinkage unsigned long __visible decompress_kernel(unsigned int started_wide,
                unsigned int command_line,
                const unsigned int rd_start,
                const unsigned int rd_end)
index 9e8c101de902c709c46c177fb3572826c7f85b7b..582fb5d1a5d5f64daa233e85828438a4c32a8bc7 100644 (file)
@@ -14,6 +14,8 @@
 #define dma_outb       outb
 #define dma_inb                inb
 
+extern unsigned long pcxl_dma_start;
+
 /*
 ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up
 ** (or rather not merge) DMAs into manageable chunks.
index a7cf0d05ccf467449759cb69d56a36d3c2a08b62..f1cc1ee3a64738912492051e507106e01ba5578a 100644 (file)
@@ -12,6 +12,10 @@ extern void mcount(void);
 extern unsigned long sys_call_table[];
 
 extern unsigned long return_address(unsigned int);
+struct ftrace_regs;
+extern void ftrace_function_trampoline(unsigned long parent,
+               unsigned long self_addr, unsigned long org_sp_gr3,
+               struct ftrace_regs *fregs);
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 extern void ftrace_caller(void);
index edfcb9858bcb7ca0bf2fee2cfeef304836beb4a5..0b326e52255e1af7176ac640fb0aff56a805a44e 100644 (file)
@@ -7,8 +7,6 @@
 #include <asm/processor.h>
 #include <asm/spinlock_types.h>
 
-#define SPINLOCK_BREAK_INSN    0x0000c006      /* break 6,6 */
-
 static inline void arch_spin_val_check(int lock_val)
 {
        if (IS_ENABLED(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK))
index d65934079ebdb032967f86976da3fc8963a84f80..efd06a897c6a3b10b6adb7a2e1b4b14abbef930a 100644 (file)
@@ -4,6 +4,10 @@
 
 #define __ARCH_SPIN_LOCK_UNLOCKED_VAL  0x1a46
 
+#define SPINLOCK_BREAK_INSN    0x0000c006      /* break 6,6 */
+
+#ifndef __ASSEMBLY__
+
 typedef struct {
 #ifdef CONFIG_PA20
        volatile unsigned int slock;
@@ -27,6 +31,8 @@ typedef struct {
        volatile unsigned int   counter;
 } arch_rwlock_t;
 
+#endif /* __ASSEMBLY__ */
+
 #define __ARCH_RW_LOCK_UNLOCKED__       0x01000000
 #define __ARCH_RW_LOCK_UNLOCKED         { .lock_mutex = __ARCH_SPIN_LOCK_UNLOCKED, \
                                        .counter = __ARCH_RW_LOCK_UNLOCKED__ }
index 0e5ebfe8d9d293efc549fa2df3069fa16c560a3b..ae03b8679696e78f4e519a73aed51475b195f99b 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/traps.h>
 #include <asm/thread_info.h>
 #include <asm/alternative.h>
+#include <asm/spinlock_types.h>
 
 #include <linux/linkage.h>
 #include <linux/pgtable.h>
        LDREG           0(\ptp),\pte
        bb,<,n          \pte,_PAGE_PRESENT_BIT,3f
        b               \fault
-       stw             \spc,0(\tmp)
+       stw             \tmp1,0(\tmp)
 99:    ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
 #endif
 2:     LDREG           0(\ptp),\pte
        .endm
 
        /* Release page_table_lock without reloading lock address.
-          Note that the values in the register spc are limited to
-          NR_SPACE_IDS (262144). Thus, the stw instruction always
-          stores a nonzero value even when register spc is 64 bits.
           We use an ordered store to ensure all prior accesses are
           performed prior to releasing the lock. */
-       .macro          ptl_unlock0     spc,tmp
+       .macro          ptl_unlock0     spc,tmp,tmp2
 #ifdef CONFIG_TLB_PTLOCK
-98:    or,COND(=)      %r0,\spc,%r0
-       stw,ma          \spc,0(\tmp)
+98:    ldi             __ARCH_SPIN_LOCK_UNLOCKED_VAL, \tmp2
+       or,COND(=)      %r0,\spc,%r0
+       stw,ma          \tmp2,0(\tmp)
 99:    ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
 #endif
        .endm
 
        /* Release page_table_lock. */
-       .macro          ptl_unlock1     spc,tmp
+       .macro          ptl_unlock1     spc,tmp,tmp2
 #ifdef CONFIG_TLB_PTLOCK
 98:    get_ptl         \tmp
-       ptl_unlock0     \spc,\tmp
+       ptl_unlock0     \spc,\tmp,\tmp2
 99:    ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
 #endif
        .endm
@@ -1125,7 +1124,7 @@ dtlb_miss_20w:
        
        idtlbt          pte,prot
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1151,7 +1150,7 @@ nadtlb_miss_20w:
 
        idtlbt          pte,prot
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1185,7 +1184,7 @@ dtlb_miss_11:
 
        mtsp            t1, %sr1        /* Restore sr1 */
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1218,7 +1217,7 @@ nadtlb_miss_11:
 
        mtsp            t1, %sr1        /* Restore sr1 */
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1247,7 +1246,7 @@ dtlb_miss_20:
 
        idtlbt          pte,prot
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1275,7 +1274,7 @@ nadtlb_miss_20:
        
        idtlbt          pte,prot
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1320,7 +1319,7 @@ itlb_miss_20w:
        
        iitlbt          pte,prot
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1344,7 +1343,7 @@ naitlb_miss_20w:
 
        iitlbt          pte,prot
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1378,7 +1377,7 @@ itlb_miss_11:
 
        mtsp            t1, %sr1        /* Restore sr1 */
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1402,7 +1401,7 @@ naitlb_miss_11:
 
        mtsp            t1, %sr1        /* Restore sr1 */
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1432,7 +1431,7 @@ itlb_miss_20:
 
        iitlbt          pte,prot
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1452,7 +1451,7 @@ naitlb_miss_20:
 
        iitlbt          pte,prot
 
-       ptl_unlock1     spc,t0
+       ptl_unlock1     spc,t0,t1
        rfir
        nop
 
@@ -1482,7 +1481,7 @@ dbit_trap_20w:
                
        idtlbt          pte,prot
 
-       ptl_unlock0     spc,t0
+       ptl_unlock0     spc,t0,t1
        rfir
        nop
 #else
@@ -1508,7 +1507,7 @@ dbit_trap_11:
 
        mtsp            t1, %sr1     /* Restore sr1 */
 
-       ptl_unlock0     spc,t0
+       ptl_unlock0     spc,t0,t1
        rfir
        nop
 
@@ -1528,7 +1527,7 @@ dbit_trap_20:
        
        idtlbt          pte,prot
 
-       ptl_unlock0     spc,t0
+       ptl_unlock0     spc,t0,t1
        rfir
        nop
 #endif
index 6d1c781eb1dbd88ff91d9aa59a301b86b3cf929a..8f37e75f2fb9caf51557d46fb7ee6070845e6bba 100644 (file)
@@ -74,8 +74,8 @@
 static DEFINE_SPINLOCK(pdc_lock);
 #endif
 
-unsigned long pdc_result[NUM_PDC_RESULT]  __aligned(8);
-unsigned long pdc_result2[NUM_PDC_RESULT] __aligned(8);
+static unsigned long pdc_result[NUM_PDC_RESULT]  __aligned(8);
+static unsigned long pdc_result2[NUM_PDC_RESULT] __aligned(8);
 
 #ifdef CONFIG_64BIT
 #define WIDE_FIRMWARE 0x1
@@ -334,7 +334,7 @@ int __pdc_cpu_rendezvous(void)
 /**
  * pdc_cpu_rendezvous_lock - Lock PDC while transitioning to rendezvous state
  */
-void pdc_cpu_rendezvous_lock(void)
+void pdc_cpu_rendezvous_lock(void) __acquires(&pdc_lock)
 {
        spin_lock(&pdc_lock);
 }
@@ -342,7 +342,7 @@ void pdc_cpu_rendezvous_lock(void)
 /**
  * pdc_cpu_rendezvous_unlock - Unlock PDC after reaching rendezvous state
  */
-void pdc_cpu_rendezvous_unlock(void)
+void pdc_cpu_rendezvous_unlock(void) __releases(&pdc_lock)
 {
        spin_unlock(&pdc_lock);
 }
index 4d392e4ed35847363b7f5f37836edaf607c64b3c..d1defb9ede70c0ae73e46363e850fc28ef91cebd 100644 (file)
@@ -53,7 +53,7 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
 
 static ftrace_func_t ftrace_func;
 
-void notrace __hot ftrace_function_trampoline(unsigned long parent,
+asmlinkage void notrace __hot ftrace_function_trampoline(unsigned long parent,
                                unsigned long self_addr,
                                unsigned long org_sp_gr3,
                                struct ftrace_regs *fregs)
index 00297e8e1c88870539aed73905ebf7b123063d8a..6f0c92e8149d828afc68824e9231703ff99f2bee 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/syscalls.h>
+#include <linux/libgcc.h>
 
 #include <linux/string.h>
 EXPORT_SYMBOL(memset);
@@ -92,12 +93,6 @@ EXPORT_SYMBOL($$divI_12);
 EXPORT_SYMBOL($$divI_14);
 EXPORT_SYMBOL($$divI_15);
 
-extern void __ashrdi3(void);
-extern void __ashldi3(void);
-extern void __lshrdi3(void);
-extern void __muldi3(void);
-extern void __ucmpdi2(void);
-
 EXPORT_SYMBOL(__ashrdi3);
 EXPORT_SYMBOL(__ashldi3);
 EXPORT_SYMBOL(__lshrdi3);
index d818ece23b4a0cdf2711230c6a084b6ec82abfd1..bf9f192c826ebe692587f72d283c4ac25a1f0b50 100644 (file)
@@ -39,7 +39,7 @@ static struct proc_dir_entry * proc_gsc_root __read_mostly = NULL;
 static unsigned long pcxl_used_bytes __read_mostly;
 static unsigned long pcxl_used_pages __read_mostly;
 
-extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */
+unsigned long pcxl_dma_start __ro_after_init; /* pcxl dma mapping area start */
 static DEFINE_SPINLOCK(pcxl_res_lock);
 static char    *pcxl_res_map;
 static int     pcxl_res_hint;
@@ -381,7 +381,7 @@ pcxl_dma_init(void)
        pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
                                            get_order(pcxl_res_size));
        memset(pcxl_res_map, 0, pcxl_res_size);
-       proc_gsc_root = proc_mkdir("gsc", NULL);
+       proc_gsc_root = proc_mkdir("bus/gsc", NULL);
        if (!proc_gsc_root)
                printk(KERN_WARNING
                        "pcxl_dma_init: Unable to create gsc /proc dir entry\n");
@@ -417,14 +417,6 @@ void *arch_dma_alloc(struct device *dev, size_t size,
        map_uncached_pages(vaddr, size, paddr);
        *dma_handle = (dma_addr_t) paddr;
 
-#if 0
-/* This probably isn't needed to support EISA cards.
-** ISA cards will certainly only support 24-bit DMA addressing.
-** Not clear if we can, want, or need to support ISA.
-*/
-       if (!dev || *dev->coherent_dma_mask < 0xffffffff)
-               gfp |= GFP_DMA;
-#endif
        return (void *)vaddr;
 }
 
index 0d24735bd9182af0e6149b5ef1faa85d705e4ec2..0f9b3b5914cf6994862568f80cc348baed60882a 100644 (file)
@@ -354,10 +354,8 @@ static int __init pdt_initcall(void)
                return -ENODEV;
 
        kpdtd_task = kthread_run(pdt_mainloop, NULL, "kpdtd");
-       if (IS_ERR(kpdtd_task))
-               return PTR_ERR(kpdtd_task);
 
-       return 0;
+       return PTR_ERR_OR_ZERO(kpdtd_task);
 }
 
 late_initcall(pdt_initcall);
index 90b04d8af21208e6206242b402d5caf20ba415e5..b0f0816879df8ff18c9f1da0ef1ce1acb3661906 100644 (file)
@@ -57,7 +57,7 @@ struct rdr_tbl_ent {
 static int perf_processor_interface __read_mostly = UNKNOWN_INTF;
 static int perf_enabled __read_mostly;
 static DEFINE_SPINLOCK(perf_lock);
-struct parisc_device *cpu_device __read_mostly;
+static struct parisc_device *cpu_device __read_mostly;
 
 /* RDRs to write for PCX-W */
 static const int perf_rdrs_W[] =
index 00b0df97afb1455287103c8590a0e987875ef17b..762289b9984ea32d0e6006101d8296dfad7d24b8 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/pdc.h>
+#include <asm/smp.h>
 #include <asm/pdcpat.h>
 #include <asm/irq.h>           /* for struct irq_region */
 #include <asm/parisc-device.h>
index 573f8303e2b05c684e9343cc1020bb77195d7e06..211a4afdd282aa0425ef50bdf21783df76f7bc33 100644 (file)
 
 static char __initdata command_line[COMMAND_LINE_SIZE];
 
-/* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
-struct proc_dir_entry * proc_runway_root __read_mostly = NULL;
-struct proc_dir_entry * proc_gsc_root __read_mostly = NULL;
-struct proc_dir_entry * proc_mckinley_root __read_mostly = NULL;
-
 static void __init setup_cmdline(char **cmdline_p)
 {
        extern unsigned int boot_args[];
@@ -196,48 +191,6 @@ const struct seq_operations cpuinfo_op = {
        .show   = show_cpuinfo
 };
 
-static void __init parisc_proc_mkdir(void)
-{
-       /*
-       ** Can't call proc_mkdir() until after proc_root_init() has been
-       ** called by start_kernel(). In other words, this code can't
-       ** live in arch/.../setup.c because start_parisc() calls
-       ** start_kernel().
-       */
-       switch (boot_cpu_data.cpu_type) {
-       case pcxl:
-       case pcxl2:
-               if (NULL == proc_gsc_root)
-               {
-                       proc_gsc_root = proc_mkdir("bus/gsc", NULL);
-               }
-               break;
-        case pcxt_:
-        case pcxu:
-        case pcxu_:
-        case pcxw:
-        case pcxw_:
-        case pcxw2:
-                if (NULL == proc_runway_root)
-                {
-                        proc_runway_root = proc_mkdir("bus/runway", NULL);
-                }
-                break;
-       case mako:
-       case mako2:
-                if (NULL == proc_mckinley_root)
-                {
-                        proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
-                }
-                break;
-       default:
-               /* FIXME: this was added to prevent the compiler 
-                * complaining about missing pcx, pcxs and pcxt
-                * I'm assuming they have neither gsc nor runway */
-               break;
-       }
-}
-
 static struct resource central_bus = {
        .name   = "Central Bus",
        .start  = F_EXTEND(0xfff80000),
@@ -294,7 +247,6 @@ static int __init parisc_init(void)
 {
        u32 osid = (OS_ID_LINUX << 16);
 
-       parisc_proc_mkdir();
        parisc_init_resources();
        do_device_inventory();                  /* probe for hardware */
 
index f886ff0c75df2d06e0df6f7ee25099b1b5413897..e8d27def6c5210ad526469149dbd3449a4a1ab60 100644 (file)
@@ -423,7 +423,7 @@ static void check_syscallno_in_delay_branch(struct pt_regs *regs)
        regs->gr[31] -= 8; /* delayed branching */
 
        /* Get assembler opcode of code in delay branch */
-       uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4);
+       uaddr = (u32 __user *) ((regs->gr[31] & ~3) + 4);
        err = get_user(opcode, uaddr);
        if (err)
                return;
index ca2d537e25b1872ab15126c28aa892a13b2ca0ed..9915062d5243c38776dcb2296faa9165e32d55bd 100644 (file)
 #include <linux/elf-randomize.h>
 
 /*
- * Construct an artificial page offset for the mapping based on the virtual
+ * Construct an artificial page offset for the mapping based on the physical
  * address of the kernel file mapping variable.
- * If filp is zero the calculated pgoff value aliases the memory of the given
- * address. This is useful for io_uring where the mapping shall alias a kernel
- * address and a userspace adress where both the kernel and the userspace
- * access the same memory region.
  */
-#define GET_FILP_PGOFF(filp, addr)             \
-       ((filp ? (((unsigned long) filp->f_mapping) >> 8)       \
-                & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL)        \
-         + (addr >> PAGE_SHIFT))
+#define GET_FILP_PGOFF(filp)           \
+       (filp ? (((unsigned long) filp->f_mapping) >> 8)        \
+                & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL)
 
 static unsigned long shared_align_offset(unsigned long filp_pgoff,
                                         unsigned long pgoff)
@@ -117,7 +112,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
        do_color_align = 0;
        if (filp || (flags & MAP_SHARED))
                do_color_align = 1;
-       filp_pgoff = GET_FILP_PGOFF(filp, addr);
+       filp_pgoff = GET_FILP_PGOFF(filp);
 
        if (flags & MAP_FIXED) {
                /* Even MAP_FIXED mappings must reside within TASK_SIZE */
index 1373e5129868f58238bd8b4ccbeb218642cfbcda..1f51aa9c8230cc369226e9c7e0a97e143303b12d 100644 (file)
@@ -39,6 +39,7 @@ registers).
 #include <asm/assembly.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
+#include <asm/spinlock_types.h>
 
 #include <linux/linkage.h>
 
@@ -66,6 +67,16 @@ registers).
        stw     \reg1, 0(%sr2,\reg2)
        .endm
 
+       /* raise exception if spinlock content is not zero or
+        * __ARCH_SPIN_LOCK_UNLOCKED_VAL */
+       .macro  spinlock_check spin_val,tmpreg
+#ifdef CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK
+       ldi     __ARCH_SPIN_LOCK_UNLOCKED_VAL, \tmpreg
+       andcm,= \spin_val, \tmpreg, %r0
+       .word   SPINLOCK_BREAK_INSN
+#endif
+       .endm
+
        .text
 
        .import syscall_exit,code
@@ -508,7 +519,8 @@ lws_start:
 
 lws_exit_noerror:
        lws_pagefault_enable    %r1,%r21
-       stw,ma  %r20, 0(%sr2,%r20)
+       ldi     __ARCH_SPIN_LOCK_UNLOCKED_VAL, %r21
+       stw,ma  %r21, 0(%sr2,%r20)
        ssm     PSW_SM_I, %r0
        b       lws_exit
        copy    %r0, %r21
@@ -521,7 +533,8 @@ lws_wouldblock:
 
 lws_pagefault:
        lws_pagefault_enable    %r1,%r21
-       stw,ma  %r20, 0(%sr2,%r20)
+       ldi     __ARCH_SPIN_LOCK_UNLOCKED_VAL, %r21
+       stw,ma  %r21, 0(%sr2,%r20)
        ssm     PSW_SM_I, %r0
        ldo     3(%r0),%r28
        b       lws_exit
@@ -619,6 +632,7 @@ lws_compare_and_swap:
 
        /* Try to acquire the lock */
        LDCW    0(%sr2,%r20), %r28
+       spinlock_check  %r28, %r21
        comclr,<>       %r0, %r28, %r0
        b,n     lws_wouldblock
 
@@ -772,6 +786,7 @@ cas2_lock_start:
 
        /* Try to acquire the lock */
        LDCW    0(%sr2,%r20), %r28
+       spinlock_check  %r28, %r21
        comclr,<>       %r0, %r28, %r0
        b,n     lws_wouldblock
 
@@ -1001,6 +1016,7 @@ atomic_xchg_start:
 
        /* Try to acquire the lock */
        LDCW    0(%sr2,%r20), %r28
+       spinlock_check  %r28, %r21
        comclr,<>       %r0, %r28, %r0
        b,n     lws_wouldblock
 
@@ -1199,6 +1215,7 @@ atomic_store_start:
 
        /* Try to acquire the lock */
        LDCW    0(%sr2,%r20), %r28
+       spinlock_check  %r28, %r21
        comclr,<>       %r0, %r28, %r0
        b,n     lws_wouldblock
 
@@ -1330,7 +1347,7 @@ ENTRY(lws_lock_start)
        /* lws locks */
        .rept 256
        /* Keep locks aligned at 16-bytes */
-       .word 1
+       .word __ARCH_SPIN_LOCK_UNLOCKED_VAL
        .word 0 
        .word 0
        .word 0
index 033b9e50b44aebc4ccaff074729890d9238247d6..170d0dda4213ebf7e7f466eb11fbda34feb21e8e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/signal.h>
 #include <linux/ratelimit.h>
 #include <linux/uaccess.h>
+#include <linux/sysctl.h>
 #include <asm/unaligned.h>
 #include <asm/hardirq.h>
 #include <asm/traps.h>
@@ -337,7 +338,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
        : "r19", "r20", "r21", "r22", "r1" );
 #else
     {
-       unsigned long valh=(val>>32),vall=(val&0xffffffffl);
+       unsigned long valh = (val >> 32), vall = (val & 0xffffffffl);
        __asm__ __volatile__ (
 "      mtsp    %4, %%sr1\n"
 "      zdep    %2, 29, 2, %%r19\n"
@@ -473,7 +474,7 @@ void handle_unaligned(struct pt_regs *regs)
        case OPCODE_LDWA_I:
        case OPCODE_LDW_S:
        case OPCODE_LDWA_S:
-               ret = emulate_ldw(regs, R3(regs->iir),0);
+               ret = emulate_ldw(regs, R3(regs->iir), 0);
                break;
 
        case OPCODE_STH:
@@ -482,7 +483,7 @@ void handle_unaligned(struct pt_regs *regs)
 
        case OPCODE_STW:
        case OPCODE_STWA:
-               ret = emulate_stw(regs, R2(regs->iir),0);
+               ret = emulate_stw(regs, R2(regs->iir), 0);
                break;
 
 #ifdef CONFIG_64BIT
@@ -490,12 +491,12 @@ void handle_unaligned(struct pt_regs *regs)
        case OPCODE_LDDA_I:
        case OPCODE_LDD_S:
        case OPCODE_LDDA_S:
-               ret = emulate_ldd(regs, R3(regs->iir),0);
+               ret = emulate_ldd(regs, R3(regs->iir), 0);
                break;
 
        case OPCODE_STD:
        case OPCODE_STDA:
-               ret = emulate_std(regs, R2(regs->iir),0);
+               ret = emulate_std(regs, R2(regs->iir), 0);
                break;
 #endif
 
@@ -503,24 +504,24 @@ void handle_unaligned(struct pt_regs *regs)
        case OPCODE_FLDWS:
        case OPCODE_FLDWXR:
        case OPCODE_FLDWSR:
-               ret = emulate_ldw(regs,FR3(regs->iir),1);
+               ret = emulate_ldw(regs, FR3(regs->iir), 1);
                break;
 
        case OPCODE_FLDDX:
        case OPCODE_FLDDS:
-               ret = emulate_ldd(regs,R3(regs->iir),1);
+               ret = emulate_ldd(regs, R3(regs->iir), 1);
                break;
 
        case OPCODE_FSTWX:
        case OPCODE_FSTWS:
        case OPCODE_FSTWXR:
        case OPCODE_FSTWSR:
-               ret = emulate_stw(regs,FR3(regs->iir),1);
+               ret = emulate_stw(regs, FR3(regs->iir), 1);
                break;
 
        case OPCODE_FSTDX:
        case OPCODE_FSTDS:
-               ret = emulate_std(regs,R3(regs->iir),1);
+               ret = emulate_std(regs, R3(regs->iir), 1);
                break;
 
        case OPCODE_LDCD_I:
index 8e6014a142ef407495a9d8e2c5c9c70bc6dfbaf1..9d8b4dbae27393c983f3d8c17b953d9b905122e5 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/module.h>
+#include <linux/libgcc.h>
 
 union ull_union {
        unsigned long long ull;
@@ -9,7 +10,7 @@ union ull_union {
        } ui;
 };
 
-int __ucmpdi2(unsigned long long a, unsigned long long b)
+word_type __ucmpdi2(unsigned long long a, unsigned long long b)
 {
        union ull_union au = {.ull = a};
        union ull_union bu = {.ull = b};
index a4c7c7630f48b1745a58a3e3cc8928faa7ef4120..2fe5b44986e0924e3981ebc1edb9d074c08e6fda 100644 (file)
@@ -192,31 +192,31 @@ int fixup_exception(struct pt_regs *regs)
  * For implementation see handle_interruption() in traps.c
  */
 static const char * const trap_description[] = {
-       [1] "High-priority machine check (HPMC)",
-       [2] "Power failure interrupt",
-       [3] "Recovery counter trap",
-       [5] "Low-priority machine check",
-       [6] "Instruction TLB miss fault",
-       [7] "Instruction access rights / protection trap",
-       [8] "Illegal instruction trap",
-       [9] "Break instruction trap",
-       [10] "Privileged operation trap",
-       [11] "Privileged register trap",
-       [12] "Overflow trap",
-       [13] "Conditional trap",
-       [14] "FP Assist Exception trap",
-       [15] "Data TLB miss fault",
-       [16] "Non-access ITLB miss fault",
-       [17] "Non-access DTLB miss fault",
-       [18] "Data memory protection/unaligned access trap",
-       [19] "Data memory break trap",
-       [20] "TLB dirty bit trap",
-       [21] "Page reference trap",
-       [22] "Assist emulation trap",
-       [25] "Taken branch trap",
-       [26] "Data memory access rights trap",
-       [27] "Data memory protection ID trap",
-       [28] "Unaligned data reference trap",
+       [1] =   "High-priority machine check (HPMC)",
+       [2] =   "Power failure interrupt",
+       [3] =   "Recovery counter trap",
+       [5] =   "Low-priority machine check",
+       [6] =   "Instruction TLB miss fault",
+       [7] =   "Instruction access rights / protection trap",
+       [8] =   "Illegal instruction trap",
+       [9] =   "Break instruction trap",
+       [10] =  "Privileged operation trap",
+       [11] =  "Privileged register trap",
+       [12] =  "Overflow trap",
+       [13] =  "Conditional trap",
+       [14] =  "FP Assist Exception trap",
+       [15] =  "Data TLB miss fault",
+       [16] =  "Non-access ITLB miss fault",
+       [17] =  "Non-access DTLB miss fault",
+       [18] =  "Data memory protection/unaligned access trap",
+       [19] =  "Data memory break trap",
+       [20] =  "TLB dirty bit trap",
+       [21] =  "Page reference trap",
+       [22] =  "Assist emulation trap",
+       [25] =  "Taken branch trap",
+       [26] =  "Data memory access rights trap",
+       [27] =  "Data memory protection ID trap",
+       [28] =  "Unaligned data reference trap",
 };
 
 const char *trap_name(unsigned long code)
index cc15d737fda64b1db0cf883dfbe622a7b0d16ad3..ae3493dae9dc90ad10f48ddb1b1d009f59759b83 100644 (file)
@@ -19,9 +19,6 @@ void notrace set_fixmap(enum fixed_addresses idx, phys_addr_t phys)
        pmd_t *pmd = pmd_offset(pud, vaddr);
        pte_t *pte;
 
-       if (pmd_none(*pmd))
-               pte = pte_alloc_kernel(pmd, vaddr);
-
        pte = pte_offset_kernel(pmd, vaddr);
        set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX));
        flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
index 406c52fe23d549a7c792813020f2fbc0771c989d..a088c243edeaa40733ead6e9200ef160cf76f6c0 100644 (file)
@@ -523,10 +523,6 @@ void mark_rodata_ro(void)
 void *parisc_vmalloc_start __ro_after_init;
 EXPORT_SYMBOL(parisc_vmalloc_start);
 
-#ifdef CONFIG_PA11
-unsigned long pcxl_dma_start __ro_after_init;
-#endif
-
 void __init mem_init(void)
 {
        /* Do sanity checks on IPC (compat) structures */
@@ -669,6 +665,39 @@ static void __init gateway_init(void)
                  PAGE_SIZE, PAGE_GATEWAY, 1);
 }
 
+static void __init fixmap_init(void)
+{
+       unsigned long addr = FIXMAP_START;
+       unsigned long end = FIXMAP_START + FIXMAP_SIZE;
+       pgd_t *pgd = pgd_offset_k(addr);
+       p4d_t *p4d = p4d_offset(pgd, addr);
+       pud_t *pud = pud_offset(p4d, addr);
+       pmd_t *pmd;
+
+       BUILD_BUG_ON(FIXMAP_SIZE > PMD_SIZE);
+
+#if CONFIG_PGTABLE_LEVELS == 3
+       if (pud_none(*pud)) {
+               pmd = memblock_alloc(PAGE_SIZE << PMD_TABLE_ORDER,
+                                    PAGE_SIZE << PMD_TABLE_ORDER);
+               if (!pmd)
+                       panic("fixmap: pmd allocation failed.\n");
+               pud_populate(NULL, pud, pmd);
+       }
+#endif
+
+       pmd = pmd_offset(pud, addr);
+       do {
+               pte_t *pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+               if (!pte)
+                       panic("fixmap: pte allocation failed.\n");
+
+               pmd_populate_kernel(&init_mm, pmd, pte);
+
+               addr += PAGE_SIZE;
+       } while (addr < end);
+}
+
 static void __init parisc_bootmem_free(void)
 {
        unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, };
@@ -683,6 +712,7 @@ void __init paging_init(void)
        setup_bootmem();
        pagetable_init();
        gateway_init();
+       fixmap_init();
        flush_cache_all_local(); /* start with known state */
        flush_tlb_all_local(NULL);
 
index 345ff0b664993584dd257f8b37039074c183fcbf..d7ee1f43d9974d4ce29a1034ac72719631176c1a 100644 (file)
@@ -27,7 +27,7 @@
  */
 void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
 {
-       void __iomem *addr;
+       uintptr_t addr;
        struct vm_struct *area;
        unsigned long offset, last_addr;
        pgprot_t pgprot;
@@ -79,10 +79,9 @@ void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
        if (!area)
                return NULL;
 
-       addr = (void __iomem *) area->addr;
-       if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
-                              phys_addr, pgprot)) {
-               vunmap(addr);
+       addr = (uintptr_t) area->addr;
+       if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
+               vunmap(area->addr);
                return NULL;
        }
 
index 8a6754ffdc7ea1b77eef1e2d7775b420fda4e624..a6c7069bec5d4ce851ea9aac1033b50cee7b9b59 100644 (file)
@@ -393,7 +393,6 @@ int validate_sp_size(unsigned long sp, struct task_struct *p,
  */
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
-#define ARCH_HAS_SPINLOCK_PREFETCH
 
 static inline void prefetch(const void *x)
 {
@@ -411,8 +410,6 @@ static inline void prefetchw(const void *x)
        __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (x));
 }
 
-#define spin_lock_prefetch(x)  prefetchw(x)
-
 /* asm stubs */
 extern unsigned long isa300_idle_stop_noloss(unsigned long psscr_val);
 extern unsigned long isa300_idle_stop_mayloss(unsigned long psscr_val);
index 46c31fb8748d554e084e8f383734da06d9e7a7eb..30a12d2086871304bde578156b71557fda67da51 100644 (file)
@@ -34,7 +34,7 @@ static inline long find_zero(unsigned long mask)
        return leading_zero_bits >> 3;
 }
 
-static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
+static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
 {
        unsigned long rhs = val | c->low_bits;
        *data = rhs;
index f132d8704263cd683f78eed26387aee0babef52c..6440b1bb332acfd7942020a65cd9f5461bc70546 100644 (file)
@@ -375,8 +375,7 @@ _GLOBAL(generic_secondary_smp_init)
        beq     20f
 
        /* start the specified thread */
-       LOAD_REG_ADDR(r5, fsl_secondary_thread_init)
-       ld      r4, 0(r5)
+       LOAD_REG_ADDR(r5, DOTSYM(fsl_secondary_thread_init))
        bl      book3e_start_thread
 
        /* stop the current thread */
index 4caf5e3079eb4b8d1fab21db26b382c5281da5a2..359577ec1680195350cd719f9d77190d297eb971 100644 (file)
@@ -709,9 +709,9 @@ static int __init rtas_flash_init(void)
        if (!rtas_validate_flash_data.buf)
                return -ENOMEM;
 
-       flash_block_cache = kmem_cache_create("rtas_flash_cache",
-                                             RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
-                                             NULL);
+       flash_block_cache = kmem_cache_create_usercopy("rtas_flash_cache",
+                                                      RTAS_BLK_SIZE, RTAS_BLK_SIZE,
+                                                      0, 0, RTAS_BLK_SIZE, NULL);
        if (!flash_block_cache) {
                printk(KERN_ERR "%s: failed to create block cache\n",
                                __func__);
index ffb1db3868499896f89584acfa74d14872892557..1f7d86de1538e20528cf099bb97063b3cdef4a36 100644 (file)
@@ -33,6 +33,9 @@
  * and then arrange for the ftrace function to be called.
  */
 .macro ftrace_regs_entry allregs
+       /* Create a minimal stack frame for representing B */
+       PPC_STLU        r1, -STACK_FRAME_MIN_SIZE(r1)
+
        /* Create our stack frame + pt_regs */
        PPC_STLU        r1,-SWITCH_FRAME_SIZE(r1)
 
@@ -42,7 +45,7 @@
 
 #ifdef CONFIG_PPC64
        /* Save the original return address in A's stack frame */
-       std     r0, LRSAVE+SWITCH_FRAME_SIZE(r1)
+       std     r0, LRSAVE+SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE(r1)
        /* Ok to continue? */
        lbz     r3, PACA_FTRACE_ENABLED(r13)
        cmpdi   r3, 0
@@ -77,6 +80,8 @@
        mflr    r7
        /* Save it as pt_regs->nip */
        PPC_STL r7, _NIP(r1)
+       /* Also save it in B's stackframe header for proper unwind */
+       PPC_STL r7, LRSAVE+SWITCH_FRAME_SIZE(r1)
        /* Save the read LR in pt_regs->link */
        PPC_STL r0, _LINK(r1)
 
 #endif
 
        /* Pop our stack frame */
-       addi r1, r1, SWITCH_FRAME_SIZE
+       addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
 
 #ifdef CONFIG_LIVEPATCH_64
         /* Based on the cmpd above, if the NIP was altered handle livepatch */
index fe1b83020e0df0c700eae0a816d5257c1059cc76..0ec5b45b1e86adc771bf85da57e3622a75b721e4 100644 (file)
@@ -314,8 +314,7 @@ void __ref vmemmap_free(unsigned long start, unsigned long end,
        start = ALIGN_DOWN(start, page_size);
        if (altmap) {
                alt_start = altmap->base_pfn;
-               alt_end = altmap->base_pfn + altmap->reserve +
-                         altmap->free + altmap->alloc + altmap->align;
+               alt_end = altmap->base_pfn + altmap->reserve + altmap->free;
        }
 
        pr_debug("vmemmap_free %lx...%lx\n", start, end);
index 9c43cf32f4c9fc4f3be82c00978ea5e5f7acb654..40aa5820688831fd22cbfc2d7c1f4a0632f9fb67 100644 (file)
@@ -180,7 +180,7 @@ static void wake_hw_thread(void *info)
        unsigned long inia;
        int cpu = *(const int *)info;
 
-       inia = *(unsigned long *)fsl_secondary_thread_init;
+       inia = ppc_function_entry(fsl_secondary_thread_init);
        book3e_start_thread(cpu_thread_in_core(cpu), inia);
 }
 #endif
index 4c5790aff1b54489b358a6c80be310b17db2ba15..8633891b7aa58027863192a5e87663190cda996b 100644 (file)
@@ -26,8 +26,8 @@
 #include <linux/rtc.h>
 #include <linux/of_address.h>
 
+#include <asm/early_ioremap.h>
 #include <asm/sections.h>
-#include <asm/io.h>
 #include <asm/machdep.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
@@ -182,7 +182,7 @@ static int __init via_calibrate_decr(void)
                return 0;
        }
        of_node_put(vias);
-       via = ioremap(rsrc.start, resource_size(&rsrc));
+       via = early_ioremap(rsrc.start, resource_size(&rsrc));
        if (via == NULL) {
                printk(KERN_ERR "Failed to map VIA for timer calibration !\n");
                return 0;
@@ -207,7 +207,7 @@ static int __init via_calibrate_decr(void)
 
        ppc_tb_freq = (dstart - dend) * 100 / 6;
 
-       iounmap(via);
+       early_iounmap((void *)via, resource_size(&rsrc));
 
        return 1;
 }
index 4c07b9189c867b715f96ec3beaf1c14a810bb2ae..10e7a7ad175aae15282b466884f0e04e1393335a 100644 (file)
@@ -570,24 +570,30 @@ config TOOLCHAIN_HAS_ZIHINTPAUSE
 config TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
        def_bool y
        # https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=aed44286efa8ae8717a77d94b51ac3614e2ca6dc
-       depends on AS_IS_GNU && AS_VERSION >= 23800
-       help
-         Newer binutils versions default to ISA spec version 20191213 which
-         moves some instructions from the I extension to the Zicsr and Zifencei
-         extensions.
+       # https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=98416dbb0a62579d4a7a4a76bab51b5b52fec2cd
+       depends on AS_IS_GNU && AS_VERSION >= 23600
+       help
+         Binutils-2.38 and GCC-12.1.0 bumped the default ISA spec to the newer
+         20191213 version, which moves some instructions from the I extension to
+         the Zicsr and Zifencei extensions. This requires explicitly specifying
+         Zicsr and Zifencei when binutils >= 2.38 or GCC >= 12.1.0. Zicsr
+         and Zifencei are supported in binutils from version 2.36 onwards.
+         To make life easier, and avoid forcing toolchains that default to a
+         newer ISA spec to version 2.2, relax the check to binutils >= 2.36.
+         For clang < 17 or GCC < 11.1.0, for which this is not possible, this is
+         dealt with in CONFIG_TOOLCHAIN_NEEDS_OLD_ISA_SPEC.
 
 config TOOLCHAIN_NEEDS_OLD_ISA_SPEC
        def_bool y
        depends on TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
        # https://github.com/llvm/llvm-project/commit/22e199e6afb1263c943c0c0d4498694e15bf8a16
-       depends on CC_IS_CLANG && CLANG_VERSION < 170000
-       help
-         Certain versions of clang do not support zicsr and zifencei via -march
-         but newer versions of binutils require it for the reasons noted in the
-         help text of CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI. This
-         option causes an older ISA spec compatible with these older versions
-         of clang to be passed to GAS, which has the same result as passing zicsr
-         and zifencei to -march.
+       # https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b03be74bad08c382da47e048007a78fa3fb4ef49
+       depends on (CC_IS_CLANG && CLANG_VERSION < 170000) || (CC_IS_GCC && GCC_VERSION < 110100)
+       help
+         Certain versions of clang and GCC do not support zicsr and zifencei via
+         -march. This option causes an older ISA spec compatible with these older
+         versions of clang and GCC to be passed to GAS, which has the same result
+         as passing zicsr and zifencei to -march.
 
 config FPU
        bool "FPU support"
index f71ce21ff684ff5f7d4c12d9bdefa671f1aa05d8..d5604d2073bc2e51f17da549381e834eca6e7779 100644 (file)
@@ -19,7 +19,7 @@ typedef u64 phys_cpuid_t;
 #define PHYS_CPUID_INVALID INVALID_HARTID
 
 /* ACPI table mapping after acpi_permanent_mmap is set */
-void *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
+void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
 #define acpi_os_ioremap acpi_os_ioremap
 
 #define acpi_strict 1  /* No out-of-spec workarounds on RISC-V */
index 8091b8bf4883fe30f3b4921648a077816c67118a..b93ffddf8a61e510048ef69ccb9e98fba46a844d 100644 (file)
@@ -37,6 +37,10 @@ static inline void flush_dcache_page(struct page *page)
 #define flush_icache_user_page(vma, pg, addr, len) \
        flush_icache_mm(vma->vm_mm, 0)
 
+#ifdef CONFIG_64BIT
+#define flush_cache_vmap(start, end)   flush_tlb_kernel_range(start, end)
+#endif
+
 #ifndef CONFIG_SMP
 
 #define flush_icache_all() local_flush_icache_all()
index 4e1505cef8aa40fd543c4c2f00bc357a6cb5c4be..fce00400c9bcc063086f3211594da45d2ca41871 100644 (file)
 #define RVC_INSN_FUNCT4_OPOFF  12
 #define RVC_INSN_FUNCT3_MASK   GENMASK(15, 13)
 #define RVC_INSN_FUNCT3_OPOFF  13
+#define RVC_INSN_J_RS1_MASK    GENMASK(11, 7)
 #define RVC_INSN_J_RS2_MASK    GENMASK(6, 2)
 #define RVC_INSN_OPCODE_MASK   GENMASK(1, 0)
 #define RVC_ENCODE_FUNCT3(f_)  (RVC_FUNCT3_##f_ << RVC_INSN_FUNCT3_OPOFF)
@@ -245,8 +246,6 @@ __RISCV_INSN_FUNCS(c_jal, RVC_MASK_C_JAL, RVC_MATCH_C_JAL)
 __RISCV_INSN_FUNCS(auipc, RVG_MASK_AUIPC, RVG_MATCH_AUIPC)
 __RISCV_INSN_FUNCS(jalr, RVG_MASK_JALR, RVG_MATCH_JALR)
 __RISCV_INSN_FUNCS(jal, RVG_MASK_JAL, RVG_MATCH_JAL)
-__RISCV_INSN_FUNCS(c_jr, RVC_MASK_C_JR, RVC_MATCH_C_JR)
-__RISCV_INSN_FUNCS(c_jalr, RVC_MASK_C_JALR, RVC_MATCH_C_JALR)
 __RISCV_INSN_FUNCS(c_j, RVC_MASK_C_J, RVC_MATCH_C_J)
 __RISCV_INSN_FUNCS(beq, RVG_MASK_BEQ, RVG_MATCH_BEQ)
 __RISCV_INSN_FUNCS(bne, RVG_MASK_BNE, RVG_MATCH_BNE)
@@ -273,6 +272,18 @@ static __always_inline bool riscv_insn_is_branch(u32 code)
        return (code & RV_INSN_OPCODE_MASK) == RVG_OPCODE_BRANCH;
 }
 
+static __always_inline bool riscv_insn_is_c_jr(u32 code)
+{
+       return (code & RVC_MASK_C_JR) == RVC_MATCH_C_JR &&
+              (code & RVC_INSN_J_RS1_MASK) != 0;
+}
+
+static __always_inline bool riscv_insn_is_c_jalr(u32 code)
+{
+       return (code & RVC_MASK_C_JALR) == RVC_MATCH_C_JALR &&
+              (code & RVC_INSN_J_RS1_MASK) != 0;
+}
+
 #define RV_IMM_SIGN(x) (-(((x) >> 31) & 1))
 #define RVC_IMM_SIGN(x) (-(((x) >> 12) & 1))
 #define RV_X(X, s, mask)  (((X) >> (s)) & (mask))
index aff6c33ab0c0837488f687c729e3f56fc38e2f5f..4c58ee7f95ecfa65ae11de96eda76347e747fe56 100644 (file)
@@ -101,9 +101,9 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
  * Relaxed I/O memory access primitives. These follow the Device memory
  * ordering rules but do not guarantee any ordering relative to Normal memory
  * accesses.  These are defined to order the indicated access (either a read or
- * write) with all other I/O memory accesses. Since the platform specification
- * defines that all I/O regions are strongly ordered on channel 2, no explicit
- * fences are required to enforce this ordering.
+ * write) with all other I/O memory accesses to the same peripheral. Since the
+ * platform specification defines that all I/O regions are strongly ordered on
+ * channel 0, no explicit fences are required to enforce this ordering.
  */
 /* FIXME: These are now the same as asm-generic */
 #define __io_rbr()             do {} while (0)
@@ -125,14 +125,14 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #endif
 
 /*
- * I/O memory access primitives. Reads are ordered relative to any
- * following Normal memory access. Writes are ordered relative to any prior
- * Normal memory access.  The memory barriers here are necessary as RISC-V
+ * I/O memory access primitives.  Reads are ordered relative to any following
+ * Normal memory read and delay() loop.  Writes are ordered relative to any
+ * prior Normal memory write.  The memory barriers here are necessary as RISC-V
  * doesn't define any ordering between the memory space and the I/O space.
  */
 #define __io_br()      do {} while (0)
-#define __io_ar(v)     __asm__ __volatile__ ("fence i,r" : : : "memory")
-#define __io_bw()      __asm__ __volatile__ ("fence w,o" : : : "memory")
+#define __io_ar(v)     ({ __asm__ __volatile__ ("fence i,ir" : : : "memory"); })
+#define __io_bw()      ({ __asm__ __volatile__ ("fence w,o" : : : "memory"); })
 #define __io_aw()      mmiowb_set_pending()
 
 #define readb(c)       ({ u8  __v; __io_br(); __v = readb_cpu(c); __io_ar(__v); __v; })
index 75970ee2bda223be83a567adab6fa327e8e58cd1..b5680c940c1e97b0c4f02ce865c7688c13a8a155 100644 (file)
@@ -188,6 +188,8 @@ extern struct pt_alloc_ops pt_ops __initdata;
 #define PAGE_KERNEL_IO         __pgprot(_PAGE_IOREMAP)
 
 extern pgd_t swapper_pg_dir[];
+extern pgd_t trampoline_pg_dir[];
+extern pgd_t early_pg_dir[];
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 static inline int pmd_present(pmd_t pmd)
index 58d3e447f191cbcfdf3283c6ceaf2b1e46cdfb0b..924d01b56c9a1eb1eacd53a923fc55591cda654f 100644 (file)
@@ -3,12 +3,14 @@
 
 #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
 
+extern bool pgtable_l4_enabled, pgtable_l5_enabled;
+
 #define IOREMAP_MAX_ORDER (PUD_SHIFT)
 
 #define arch_vmap_pud_supported arch_vmap_pud_supported
 static inline bool arch_vmap_pud_supported(pgprot_t prot)
 {
-       return true;
+       return pgtable_l4_enabled || pgtable_l5_enabled;
 }
 
 #define arch_vmap_pmd_supported arch_vmap_pmd_supported
diff --git a/arch/riscv/include/uapi/asm/bitsperlong.h b/arch/riscv/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..7d0b32e
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2015 Regents of the University of California
+ */
+
+#ifndef _UAPI_ASM_RISCV_BITSPERLONG_H
+#define _UAPI_ASM_RISCV_BITSPERLONG_H
+
+#define __BITS_PER_LONG (__SIZEOF_POINTER__ * 8)
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* _UAPI_ASM_RISCV_BITSPERLONG_H */
index 5ee03ebab80e5af633ac086e79436688ad6cd9d5..56cb2c986c4857a9990fbfec9301df90f410162e 100644 (file)
@@ -215,9 +215,9 @@ void __init __acpi_unmap_table(void __iomem *map, unsigned long size)
        early_iounmap(map, size);
 }
 
-void *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
+void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
 {
-       return memremap(phys, size, MEMREMAP_WB);
+       return (void __iomem *)memremap(phys, size, MEMREMAP_WB);
 }
 
 #ifdef CONFIG_PCI
index 189345773e7e10d427913a481db27c7892fac0a3..b86e5e2c3aea94e13ebce84db247a2e8ab5934df 100644 (file)
@@ -11,7 +11,13 @@ compat_vdso-syms += flush_icache
 COMPAT_CC := $(CC)
 COMPAT_LD := $(LD)
 
-COMPAT_CC_FLAGS := -march=rv32g -mabi=ilp32
+# binutils 2.35 does not support the zifencei extension, but in the ISA
+# spec 20191213, G stands for IMAFD_ZICSR_ZIFENCEI.
+ifdef CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
+       COMPAT_CC_FLAGS := -march=rv32g -mabi=ilp32
+else
+       COMPAT_CC_FLAGS := -march=rv32imafd -mabi=ilp32
+endif
 COMPAT_LD_FLAGS := -melf32lriscv
 
 # Disable attributes, as they're useless and break the build.
index a2fc952318e9f903dc2232c89106e82c3edfcc07..35b854cf078ed67fe1318492fce7418e7b56a6c0 100644 (file)
 #include <asm/smp.h>
 #include <asm/pgtable.h>
 
+bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
+{
+       return phys_id == cpuid_to_hartid_map(cpu);
+}
+
 /*
  * Returns the hart ID of the given device tree node, or -ENODEV if the node
  * isn't an enabled and valid RISC-V hart node.
index b351a3c013555650b6ad4f75e0b7e2de28c8ba81..55f1d7856b5448c9242df00be2d49d061d4d15b2 100644 (file)
@@ -18,4 +18,6 @@ void arch_crash_save_vmcoreinfo(void)
        vmcoreinfo_append_str("NUMBER(MODULES_END)=0x%lx\n", MODULES_END);
 #endif
        vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR);
+       vmcoreinfo_append_str("NUMBER(va_kernel_pa_offset)=0x%lx\n",
+                                               kernel_map.va_kernel_pa_offset);
 }
index 5372b708fae21a072f72434625d27d792b83abc7..c08bb5c3b38578d26b07d30d6c2fcb2c91977863 100644 (file)
@@ -281,7 +281,7 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf,
                kbuf.buffer = initrd;
                kbuf.bufsz = kbuf.memsz = initrd_len;
                kbuf.buf_align = PAGE_SIZE;
-               kbuf.top_down = false;
+               kbuf.top_down = true;
                kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
                ret = kexec_add_buffer(&kbuf);
                if (ret)
@@ -425,6 +425,7 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
                 * sym, instead of searching the whole relsec.
                 */
                case R_RISCV_PCREL_HI20:
+               case R_RISCV_CALL_PLT:
                case R_RISCV_CALL:
                        *(u64 *)loc = CLEAN_IMM(UITYPE, *(u64 *)loc) |
                                 ENCODE_UJTYPE_IMM(val - addr);
index d0577cc6a0813f8b05661e25e701902492f75ec5..a8efa053c4a524c830982f9df12453c40b960340 100644 (file)
@@ -84,6 +84,9 @@ void do_softirq_own_stack(void)
                : [sp] "r" (sp)
                : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
                  "t0", "t1", "t2", "t3", "t4", "t5", "t6",
+#ifndef CONFIG_FRAME_POINTER
+                 "s0",
+#endif
                  "memory");
        } else
 #endif
index 85bbce0f758cbcc6f3204a14a8600c13f1d2f476..40420afbb1a09fc90ea00107816adde1002d6479 100644 (file)
@@ -61,11 +61,6 @@ int riscv_hartid_to_cpuid(unsigned long hartid)
        return -ENOENT;
 }
 
-bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
-{
-       return phys_id == cpuid_to_hartid_map(cpu);
-}
-
 static void ipi_stop(void)
 {
        set_cpu_online(smp_processor_id(), false);
index f910dfccbf5d2aaf5b838cdbfd809f8e937bdfd5..f798c853bede68f112ed14c836033c36f7adb3d5 100644 (file)
@@ -297,7 +297,7 @@ asmlinkage __visible __trap_section void do_trap_break(struct pt_regs *regs)
 asmlinkage __visible __trap_section void do_trap_ecall_u(struct pt_regs *regs)
 {
        if (user_mode(regs)) {
-               ulong syscall = regs->a7;
+               long syscall = regs->a7;
 
                regs->epc += 4;
                regs->orig_a0 = regs->a0;
@@ -306,9 +306,9 @@ asmlinkage __visible __trap_section void do_trap_ecall_u(struct pt_regs *regs)
 
                syscall = syscall_enter_from_user_mode(regs, syscall);
 
-               if (syscall < NR_syscalls)
+               if (syscall >= 0 && syscall < NR_syscalls)
                        syscall_handler(regs, syscall);
-               else
+               else if (syscall != -1)
                        regs->a0 = -ENOSYS;
 
                syscall_exit_to_user_mode(regs);
@@ -372,6 +372,9 @@ asmlinkage void noinstr do_irq(struct pt_regs *regs)
                : [sp] "r" (sp), [regs] "r" (regs)
                : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
                  "t0", "t1", "t2", "t3", "t4", "t5", "t6",
+#ifndef CONFIG_FRAME_POINTER
+                 "s0",
+#endif
                  "memory");
        } else
 #endif
index ec486e5369d9bf5b274bcd73b242666d2b216322..09b47ebacf2e8743bc1cf77be0693b4499748afb 100644 (file)
@@ -17,8 +17,11 @@ ENTRY(__asm_copy_from_user)
        li t6, SR_SUM
        csrs CSR_STATUS, t6
 
-       /* Save for return value */
-       mv      t5, a2
+       /*
+        * Save the terminal address which will be used to compute the number
+        * of bytes copied in case of a fixup exception.
+        */
+       add     t5, a0, a2
 
        /*
         * Register allocation for code below:
@@ -176,7 +179,7 @@ ENTRY(__asm_copy_from_user)
 10:
        /* Disable access to user memory */
        csrc CSR_STATUS, t6
-       mv a0, t5
+       sub a0, t5, a0
        ret
 ENDPROC(__asm_copy_to_user)
 ENDPROC(__asm_copy_from_user)
@@ -228,7 +231,7 @@ ENTRY(__clear_user)
 11:
        /* Disable access to user memory */
        csrc CSR_STATUS, t6
-       mv a0, a1
+       sub a0, a3, a0
        ret
 ENDPROC(__clear_user)
 EXPORT_SYMBOL(__clear_user)
index 9ce504737d18582b0a91152a885d5f0686fd6423..e4c35ac2357f78fb3b2ef682372598da992588e6 100644 (file)
 #include <linux/kfence.h>
 
 #include <asm/fixmap.h>
-#include <asm/tlbflush.h>
-#include <asm/sections.h>
-#include <asm/soc.h>
 #include <asm/io.h>
-#include <asm/ptdump.h>
 #include <asm/numa.h>
+#include <asm/pgtable.h>
+#include <asm/ptdump.h>
+#include <asm/sections.h>
+#include <asm/soc.h>
+#include <asm/tlbflush.h>
 
 #include "../kernel/head.h"
 
@@ -214,8 +215,13 @@ static void __init setup_bootmem(void)
        memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
 
        phys_ram_end = memblock_end_of_DRAM();
+
+       /*
+        * Make sure we align the start of the memory on a PMD boundary so that
+        * at worst, we map the linear mapping with PMD mappings.
+        */
        if (!IS_ENABLED(CONFIG_XIP_KERNEL))
-               phys_ram_base = memblock_start_of_DRAM();
+               phys_ram_base = memblock_start_of_DRAM() & PMD_MASK;
 
        /*
         * In 64-bit, any use of __va/__pa before this point is wrong as we
index 8fc0efcf905c9717f38d014d3b08bd965480f354..a01bc15dce2441d82b1508d16fb827364183fe29 100644 (file)
@@ -22,7 +22,6 @@
  * region is not and then we have to go down to the PUD level.
  */
 
-extern pgd_t early_pg_dir[PTRS_PER_PGD];
 pgd_t tmp_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
 p4d_t tmp_p4d[PTRS_PER_P4D] __page_aligned_bss;
 pud_t tmp_pud[PTRS_PER_PUD] __page_aligned_bss;
index d03d4cb9332c57f599e672380c2bc6c211177661..3a6a9a88bd38c1d48ad6a454118261fba97b2675 100644 (file)
@@ -116,7 +116,6 @@ CONFIG_UNIX=y
 CONFIG_UNIX_DIAG=m
 CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=m
-CONFIG_NET_TC_SKB_EXT=y
 CONFIG_SMC=m
 CONFIG_SMC_DIAG=m
 CONFIG_INET=y
@@ -193,6 +192,7 @@ CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NFT_HASH=m
 CONFIG_NFT_FIB_INET=m
+CONFIG_NETFILTER_XTABLES_COMPAT=y
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -379,6 +379,7 @@ CONFIG_NET_ACT_SIMP=m
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
 CONFIG_NET_ACT_GATE=m
+CONFIG_NET_TC_SKB_EXT=y
 CONFIG_DNS_RESOLVER=y
 CONFIG_OPENVSWITCH=m
 CONFIG_VSOCKETS=m
@@ -395,6 +396,7 @@ CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_SAFE=y
+# CONFIG_FW_LOADER is not set
 CONFIG_CONNECTOR=y
 CONFIG_ZRAM=y
 CONFIG_BLK_DEV_LOOP=m
@@ -502,7 +504,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_GOOGLE is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_LITEX is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
@@ -542,6 +543,7 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_TI is not set
 # CONFIG_NET_VENDOR_VERTEXCOM is not set
 # CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_NET_VENDOR_XILINX is not set
 CONFIG_PPP=m
@@ -646,7 +648,6 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_TMPFS_INODE64=y
 CONFIG_HUGETLBFS=y
-CONFIG_CONFIGFS_FS=m
 CONFIG_ECRYPT_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
@@ -690,7 +691,6 @@ CONFIG_HARDENED_USERCOPY=y
 CONFIG_FORTIFY_SOURCE=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_DISABLE=y
 CONFIG_SECURITY_LOCKDOWN_LSM=y
 CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
 CONFIG_SECURITY_LANDLOCK=y
@@ -744,7 +744,6 @@ CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_SM3_GENERIC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_WP512=m
@@ -844,6 +843,7 @@ CONFIG_PREEMPT_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_FTRACE_SYSCALLS=y
 CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_USER_EVENTS=y
 CONFIG_HIST_TRIGGERS=y
 CONFIG_FTRACE_STARTUP_TEST=y
 # CONFIG_EVENT_TRACE_STARTUP_TEST is not set
@@ -866,6 +866,7 @@ CONFIG_FAIL_MAKE_REQUEST=y
 CONFIG_FAIL_IO_TIMEOUT=y
 CONFIG_FAIL_FUTEX=y
 CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_CONFIGFS=y
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
 CONFIG_LKDTM=m
 CONFIG_TEST_MIN_HEAP=y
index 1855759cdc6aa389c05e02efdf01278ed743c553..b13a5a0d99d2591269257d92bb61d10efb11de22 100644 (file)
@@ -107,7 +107,6 @@ CONFIG_UNIX=y
 CONFIG_UNIX_DIAG=m
 CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=m
-CONFIG_NET_TC_SKB_EXT=y
 CONFIG_SMC=m
 CONFIG_SMC_DIAG=m
 CONFIG_INET=y
@@ -184,6 +183,7 @@ CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NFT_HASH=m
 CONFIG_NFT_FIB_INET=m
+CONFIG_NETFILTER_XTABLES_COMPAT=y
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -369,6 +369,7 @@ CONFIG_NET_ACT_SIMP=m
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
 CONFIG_NET_ACT_GATE=m
+CONFIG_NET_TC_SKB_EXT=y
 CONFIG_DNS_RESOLVER=y
 CONFIG_OPENVSWITCH=m
 CONFIG_VSOCKETS=m
@@ -385,6 +386,7 @@ CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_UEVENT_HELPER=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_SAFE=y
+# CONFIG_FW_LOADER is not set
 CONFIG_CONNECTOR=y
 CONFIG_ZRAM=y
 CONFIG_BLK_DEV_LOOP=m
@@ -492,7 +494,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_GOOGLE is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_LITEX is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
@@ -532,6 +533,7 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_TI is not set
 # CONFIG_NET_VENDOR_VERTEXCOM is not set
 # CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_NET_VENDOR_XILINX is not set
 CONFIG_PPP=m
@@ -673,7 +675,6 @@ CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_DISABLE=y
 CONFIG_SECURITY_LOCKDOWN_LSM=y
 CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
 CONFIG_SECURITY_LANDLOCK=y
@@ -729,7 +730,6 @@ CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_SM3_GENERIC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_WP512=m
@@ -793,6 +793,7 @@ CONFIG_STACK_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_FTRACE_SYSCALLS=y
 CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_USER_EVENTS=y
 CONFIG_HIST_TRIGGERS=y
 CONFIG_SAMPLES=y
 CONFIG_SAMPLE_TRACE_PRINTK=m
index 6f68b39817effcfc5f5a9612cd52ec465630be53..e62fb20151028fd53cbf28b065694ee81b778f01 100644 (file)
@@ -53,7 +53,6 @@ CONFIG_ZFCP=y
 # CONFIG_HVC_IUCV is not set
 # CONFIG_HW_RANDOM_S390 is not set
 # CONFIG_HMC_DRV is not set
-# CONFIG_S390_UV_UAPI is not set
 # CONFIG_S390_TAPE is not set
 # CONFIG_VMCP is not set
 # CONFIG_MONWRITER is not set
index f0fe3bcc78a87357b205782b40f21554e053f789..bb0826024bb95202fa035829567cc8ab53afe069 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _UAPI_S390_PTRACE_H
 #define _UAPI_S390_PTRACE_H
 
+#include <linux/const.h>
+
 /*
  * Offsets in the user_regs_struct. They are used for the ptrace
  * system call and in entry.S
index 4d141e2c132e5d5ad38ef6b132c69f4f607fd899..2ea7f208f0e734c1752c7d8e1de166e0d1c8c7d3 100644 (file)
@@ -459,9 +459,9 @@ static int sthyi_update_cache(u64 *rc)
  *
  * Fills the destination with system information returned by the STHYI
  * instruction. The data is generated by emulation or execution of STHYI,
- * if available. The return value is the condition code that would be
- * returned, the rc parameter is the return code which is passed in
- * register R2 + 1.
+ * if available. The return value is either a negative error value or
+ * the condition code that would be returned, the rc parameter is the
+ * return code which is passed in register R2 + 1.
  */
 int sthyi_fill(void *dst, u64 *rc)
 {
index 954d39adf85cd3034f9d28d5e87d4e36f3f228b7..341abafb96e49aa43358c8b02a7ce43a4acf34d2 100644 (file)
@@ -389,8 +389,8 @@ static int handle_partial_execution(struct kvm_vcpu *vcpu)
  */
 int handle_sthyi(struct kvm_vcpu *vcpu)
 {
-       int reg1, reg2, r = 0;
-       u64 code, addr, cc = 0, rc = 0;
+       int reg1, reg2, cc = 0, r = 0;
+       u64 code, addr, rc = 0;
        struct sthyi_sctns *sctns = NULL;
 
        if (!test_kvm_facility(vcpu->kvm, 74))
@@ -421,7 +421,10 @@ int handle_sthyi(struct kvm_vcpu *vcpu)
                return -ENOMEM;
 
        cc = sthyi_fill(sctns, &rc);
-
+       if (cc < 0) {
+               free_page((unsigned long)sctns);
+               return cc;
+       }
 out:
        if (!cc) {
                if (kvm_s390_pv_cpu_is_protected(vcpu)) {
index b26649233d124984018633396fc7df6ea4adda74..24a66670f5c3a1b788787818b5a028ce860040d5 100644 (file)
@@ -763,6 +763,8 @@ void __init vmem_map_init(void)
        if (static_key_enabled(&cpu_has_bear))
                set_memory_nx(0, 1);
        set_memory_nx(PAGE_SIZE, 1);
+       if (debug_pagealloc_enabled())
+               set_memory_4k(0, ident_map_size >> PAGE_SHIFT);
 
        pr_info("Write protected kernel read-only data: %luk\n",
                (unsigned long)(__end_rodata - _stext) >> 10);
index 2667f35d5ea5678c64cc99ded20af2b797754967..0a0d5c3d184c751d232a00e73357c0e345695a94 100644 (file)
@@ -213,7 +213,6 @@ unsigned long __get_wchan(struct task_struct *task);
  */
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
-#define ARCH_HAS_SPINLOCK_PREFETCH
 
 static inline void prefetch(const void *x)
 {
@@ -239,8 +238,6 @@ static inline void prefetchw(const void *x)
                             : "r" (x));
 }
 
-#define spin_lock_prefetch(x)  prefetchw(x)
-
 #define HAVE_ARCH_PICK_MMAP_LAYOUT
 
 int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap);
index 7422db4097701c96710ce67054a9f0c7edc6ec1b..e36261b4ea14f2e245c02987eaf3dfae804a5567 100644 (file)
@@ -2593,6 +2593,13 @@ config CPU_IBRS_ENTRY
          This mitigates both spectre_v2 and retbleed at great cost to
          performance.
 
+config CPU_SRSO
+       bool "Mitigate speculative RAS overflow on AMD"
+       depends on CPU_SUP_AMD && X86_64 && RETHUNK
+       default y
+       help
+         Enable the SRSO mitigation needed on AMD Zen1-4 machines.
+
 config SLS
        bool "Mitigate Straight-Line-Speculation"
        depends on CC_HAS_SLS && X86_64
@@ -2603,6 +2610,25 @@ config SLS
          against straight line speculation. The kernel image might be slightly
          larger.
 
+config GDS_FORCE_MITIGATION
+       bool "Force GDS Mitigation"
+       depends on CPU_SUP_INTEL
+       default n
+       help
+         Gather Data Sampling (GDS) is a hardware vulnerability which allows
+         unprivileged speculative access to data which was previously stored in
+         vector registers.
+
+         This option is equivalent to setting gather_data_sampling=force on the
+         command line. The microcode mitigation is used if present, otherwise
+         AVX is disabled as a mitigation. On affected systems that are missing
+         the microcode any userspace code that unconditionally uses AVX will
+         break with this option set.
+
+         Setting this option on systems not vulnerable to GDS has no effect.
+
+         If in doubt, say N.
+
 endif
 
 config ARCH_HAS_ADD_PAGES
index 6debb816e83dcc85321e80f1c6db00d23ad3351f..3cdf94b4145674c547a6604875fb4c26590e562a 100644 (file)
@@ -63,7 +63,14 @@ void load_stage2_idt(void)
        set_idt_entry(X86_TRAP_PF, boot_page_fault);
 
 #ifdef CONFIG_AMD_MEM_ENCRYPT
-       set_idt_entry(X86_TRAP_VC, boot_stage2_vc);
+       /*
+        * Clear the second stage #VC handler in case guest types
+        * needing #VC have not been detected.
+        */
+       if (sev_status & BIT(1))
+               set_idt_entry(X86_TRAP_VC, boot_stage2_vc);
+       else
+               set_idt_entry(X86_TRAP_VC, NULL);
 #endif
 
        load_boot_idt(&boot_idt_desc);
index 09dc8c187b3cc75236f0772311f3b9f13950a3f2..c3e343bd4760e0ab9961065f0e3b81cb54e86387 100644 (file)
@@ -404,13 +404,46 @@ void sev_enable(struct boot_params *bp)
        if (bp)
                bp->cc_blob_address = 0;
 
+       /*
+        * Do an initial SEV capability check before snp_init() which
+        * loads the CPUID page and the same checks afterwards are done
+        * without the hypervisor and are trustworthy.
+        *
+        * If the HV fakes SEV support, the guest will crash'n'burn
+        * which is good enough.
+        */
+
+       /* Check for the SME/SEV support leaf */
+       eax = 0x80000000;
+       ecx = 0;
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+       if (eax < 0x8000001f)
+               return;
+
+       /*
+        * Check for the SME/SEV feature:
+        *   CPUID Fn8000_001F[EAX]
+        *   - Bit 0 - Secure Memory Encryption support
+        *   - Bit 1 - Secure Encrypted Virtualization support
+        *   CPUID Fn8000_001F[EBX]
+        *   - Bits 5:0 - Pagetable bit position used to indicate encryption
+        */
+       eax = 0x8000001f;
+       ecx = 0;
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+       /* Check whether SEV is supported */
+       if (!(eax & BIT(1)))
+               return;
+
        /*
         * Setup/preliminary detection of SNP. This will be sanity-checked
         * against CPUID/MSR values later.
         */
        snp = snp_init(bp);
 
-       /* Check for the SME/SEV support leaf */
+       /* Now repeat the checks with the SNP CPUID table. */
+
+       /* Recheck the SME/SEV support leaf */
        eax = 0x80000000;
        ecx = 0;
        native_cpuid(&eax, &ebx, &ecx, &edx);
@@ -418,7 +451,7 @@ void sev_enable(struct boot_params *bp)
                return;
 
        /*
-        * Check for the SME/SEV feature:
+        * Recheck for the SME/SEV feature:
         *   CPUID Fn8000_001F[EAX]
         *   - Bit 0 - Secure Memory Encryption support
         *   - Bit 1 - Secure Encrypted Virtualization support
index 11a5c68d1218545da2dba1135a81ccc8a4b42d16..7645730dc228f960e69373f860ccfca811097a84 100644 (file)
@@ -299,8 +299,8 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
 
        /* Round the lowest possible end address up to a PMD boundary. */
        end = (start + len + PMD_SIZE - 1) & PMD_MASK;
-       if (end >= TASK_SIZE_MAX)
-               end = TASK_SIZE_MAX;
+       if (end >= DEFAULT_MAP_WINDOW)
+               end = DEFAULT_MAP_WINDOW;
        end -= len;
 
        if (end > start) {
index 1fbda2f94184e309f8784e2ac2f01f418d9e7385..b21335e6a210e6fba31e955c05e48504aa6a6353 100644 (file)
@@ -107,7 +107,6 @@ static bool cpu_is_self(int cpu)
 static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
                bool exclude_self)
 {
-       struct hv_send_ipi_ex **arg;
        struct hv_send_ipi_ex *ipi_arg;
        unsigned long flags;
        int nr_bank = 0;
@@ -117,9 +116,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
                return false;
 
        local_irq_save(flags);
-       arg = (struct hv_send_ipi_ex **)this_cpu_ptr(hyperv_pcpu_input_arg);
+       ipi_arg = *this_cpu_ptr(hyperv_pcpu_input_arg);
 
-       ipi_arg = *arg;
        if (unlikely(!ipi_arg))
                goto ipi_mask_ex_done;
 
index 6c04b52f139b5e54ec7e3363cdd3eba3cc3a16b8..953e280c07c385659450b6dc2c893843ac1efc20 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/apic.h>
 #include <asm/desc.h>
 #include <asm/sev.h>
+#include <asm/ibt.h>
 #include <asm/hypervisor.h>
 #include <asm/hyperv-tlfs.h>
 #include <asm/mshyperv.h>
@@ -471,6 +472,26 @@ void __init hyperv_init(void)
                wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
        }
 
+       /*
+        * Some versions of Hyper-V that provide IBT in guest VMs have a bug
+        * in that there's no ENDBR64 instruction at the entry to the
+        * hypercall page. Because hypercalls are invoked via an indirect call
+        * to the hypercall page, all hypercall attempts fail when IBT is
+        * enabled, and Linux panics. For such buggy versions, disable IBT.
+        *
+        * Fixed versions of Hyper-V always provide ENDBR64 on the hypercall
+        * page, so if future Linux kernel versions enable IBT for 32-bit
+        * builds, additional hypercall page hackery will be required here
+        * to provide an ENDBR32.
+        */
+#ifdef CONFIG_X86_KERNEL_IBT
+       if (cpu_feature_enabled(X86_FEATURE_IBT) &&
+           *(u32 *)hv_hypercall_pg != gen_endbr()) {
+               setup_clear_cpu_cap(X86_FEATURE_IBT);
+               pr_warn("Hyper-V: Disabling IBT because of Hyper-V bug\n");
+       }
+#endif
+
        /*
         * hyperv_init() is called before LAPIC is initialized: see
         * apic_intr_mode_init() -> x86_platform.apic_post_init() and
index 85d38b9f35861b65eafe3b4323bfae2f99e5fab3..db5d2ea39fc0d2389613b4cba8291af52d64c2f5 100644 (file)
@@ -25,6 +25,10 @@ void __init hv_vtl_init_platform(void)
        x86_init.irqs.pre_vector_init = x86_init_noop;
        x86_init.timers.timer_init = x86_init_noop;
 
+       /* Avoid searching for BIOS MP tables */
+       x86_init.mpparse.find_smp_config = x86_init_noop;
+       x86_init.mpparse.get_smp_config = x86_init_uint_noop;
+
        x86_platform.get_wallclock = get_rtc_noop;
        x86_platform.set_wallclock = set_rtc_noop;
        x86_platform.get_nmi_reason = hv_get_nmi_reason;
index 14f46ad2ca644dc92ec1501d2e5d26d1e2a9697f..28be6df88063974d61eeab55cd97c89b216318a3 100644 (file)
@@ -247,7 +247,7 @@ EXPORT_SYMBOL_GPL(hv_ghcb_msr_read);
 static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
                           enum hv_mem_host_visibility visibility)
 {
-       struct hv_gpa_range_for_visibility **input_pcpu, *input;
+       struct hv_gpa_range_for_visibility *input;
        u16 pages_processed;
        u64 hv_status;
        unsigned long flags;
@@ -263,9 +263,8 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
        }
 
        local_irq_save(flags);
-       input_pcpu = (struct hv_gpa_range_for_visibility **)
-                       this_cpu_ptr(hyperv_pcpu_input_arg);
-       input = *input_pcpu;
+       input = *this_cpu_ptr(hyperv_pcpu_input_arg);
+
        if (unlikely(!input)) {
                local_irq_restore(flags);
                return -EINVAL;
index 8460bd35e10c3d3571efc03ec9eb18bf246f9f1a..1cc113200ff55879186e7fcf0eea7c0ac07a494b 100644 (file)
@@ -61,7 +61,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
                                   const struct flush_tlb_info *info)
 {
        int cpu, vcpu, gva_n, max_gvas;
-       struct hv_tlb_flush **flush_pcpu;
        struct hv_tlb_flush *flush;
        u64 status;
        unsigned long flags;
@@ -74,10 +73,7 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
 
        local_irq_save(flags);
 
-       flush_pcpu = (struct hv_tlb_flush **)
-                    this_cpu_ptr(hyperv_pcpu_input_arg);
-
-       flush = *flush_pcpu;
+       flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
 
        if (unlikely(!flush)) {
                local_irq_restore(flags);
@@ -178,17 +174,13 @@ static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
                                      const struct flush_tlb_info *info)
 {
        int nr_bank = 0, max_gvas, gva_n;
-       struct hv_tlb_flush_ex **flush_pcpu;
        struct hv_tlb_flush_ex *flush;
        u64 status;
 
        if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
                return HV_STATUS_INVALID_PARAMETER;
 
-       flush_pcpu = (struct hv_tlb_flush_ex **)
-                    this_cpu_ptr(hyperv_pcpu_input_arg);
-
-       flush = *flush_pcpu;
+       flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
 
        if (info->mm) {
                /*
index 5d70968c85382560f6d7112b778a935d7a3466fa..9dc259fa322e0c388bc06c5c88b8b270ca25c712 100644 (file)
@@ -19,7 +19,6 @@
 
 int hyperv_flush_guest_mapping(u64 as)
 {
-       struct hv_guest_mapping_flush **flush_pcpu;
        struct hv_guest_mapping_flush *flush;
        u64 status;
        unsigned long flags;
@@ -30,10 +29,7 @@ int hyperv_flush_guest_mapping(u64 as)
 
        local_irq_save(flags);
 
-       flush_pcpu = (struct hv_guest_mapping_flush **)
-               this_cpu_ptr(hyperv_pcpu_input_arg);
-
-       flush = *flush_pcpu;
+       flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
 
        if (unlikely(!flush)) {
                local_irq_restore(flags);
@@ -90,7 +86,6 @@ EXPORT_SYMBOL_GPL(hyperv_fill_flush_guest_mapping_list);
 int hyperv_flush_guest_mapping_range(u64 as,
                hyperv_fill_flush_list_func fill_flush_list_func, void *data)
 {
-       struct hv_guest_mapping_flush_list **flush_pcpu;
        struct hv_guest_mapping_flush_list *flush;
        u64 status;
        unsigned long flags;
@@ -102,10 +97,8 @@ int hyperv_flush_guest_mapping_range(u64 as,
 
        local_irq_save(flags);
 
-       flush_pcpu = (struct hv_guest_mapping_flush_list **)
-               this_cpu_ptr(hyperv_pcpu_input_arg);
+       flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
 
-       flush = *flush_pcpu;
        if (unlikely(!flush)) {
                local_irq_restore(flags);
                goto fault;
index 8eb74cf386dbe5cac24c25fca9422a99212ab9b7..c8a7fc23f63c672456721888db9e293fbf70dafb 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
  *  Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
  */
-#include <acpi/pdc_intel.h>
+#include <acpi/proc_cap_intel.h>
 
 #include <asm/numa.h>
 #include <asm/fixmap.h>
@@ -15,6 +15,7 @@
 #include <asm/mpspec.h>
 #include <asm/x86_init.h>
 #include <asm/cpufeature.h>
+#include <asm/irq_vectors.h>
 
 #ifdef CONFIG_ACPI_APEI
 # include <asm/pgtable_types.h>
@@ -31,6 +32,7 @@ extern int acpi_skip_timer_override;
 extern int acpi_use_timer_override;
 extern int acpi_fix_pin2_polarity;
 extern int acpi_disable_cmcff;
+extern bool acpi_int_src_ovr[NR_IRQS_LEGACY];
 
 extern u8 acpi_sci_flags;
 extern u32 acpi_sci_override_gsi;
@@ -100,23 +102,31 @@ static inline bool arch_has_acpi_pdc(void)
                c->x86_vendor == X86_VENDOR_CENTAUR);
 }
 
-static inline void arch_acpi_set_pdc_bits(u32 *buf)
+static inline void arch_acpi_set_proc_cap_bits(u32 *cap)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
 
-       buf[2] |= ACPI_PDC_C_CAPABILITY_SMP;
+       *cap |= ACPI_PROC_CAP_C_CAPABILITY_SMP;
+
+       /* Enable coordination with firmware's _TSD info */
+       *cap |= ACPI_PROC_CAP_SMP_T_SWCOORD;
 
        if (cpu_has(c, X86_FEATURE_EST))
-               buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
+               *cap |= ACPI_PROC_CAP_EST_CAPABILITY_SWSMP;
 
        if (cpu_has(c, X86_FEATURE_ACPI))
-               buf[2] |= ACPI_PDC_T_FFH;
+               *cap |= ACPI_PROC_CAP_T_FFH;
+
+       if (cpu_has(c, X86_FEATURE_HWP))
+               *cap |= ACPI_PROC_CAP_COLLAB_PROC_PERF;
 
        /*
-        * If mwait/monitor is unsupported, C2/C3_FFH will be disabled
+        * If mwait/monitor is unsupported, C_C1_FFH and
+        * C2/C3_FFH will be disabled.
         */
-       if (!cpu_has(c, X86_FEATURE_MWAIT))
-               buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
+       if (!cpu_has(c, X86_FEATURE_MWAIT) ||
+           boot_option_idle_override == IDLE_NOMWAIT)
+               *cap &= ~(ACPI_PROC_CAP_C_C1_FFH | ACPI_PROC_CAP_C_C2C3_FFH);
 }
 
 static inline bool acpi_has_cpu_in_madt(void)
index cb8ca46213bed0a837d9e134877f623c4e0e0525..b69b0d7756aab7fc4ca5e7660c7317f9ae0132c3 100644 (file)
@@ -14,7 +14,7 @@
  * Defines x86 CPU feature bits
  */
 #define NCAPINTS                       21         /* N 32-bit words worth of info */
-#define NBUGINTS                       1          /* N 32-bit bug flags */
+#define NBUGINTS                       2          /* N 32-bit bug flags */
 
 /*
  * Note: If the comment begins with a quoted string, that string is used
 #define X86_FEATURE_SMBA               (11*32+21) /* "" Slow Memory Bandwidth Allocation */
 #define X86_FEATURE_BMEC               (11*32+22) /* "" Bandwidth Monitoring Event Configuration */
 
+#define X86_FEATURE_SRSO               (11*32+24) /* "" AMD BTB untrain RETs */
+#define X86_FEATURE_SRSO_ALIAS         (11*32+25) /* "" AMD BTB untrain RETs through aliasing */
+#define X86_FEATURE_IBPB_ON_VMEXIT     (11*32+26) /* "" Issue an IBPB only on VMEXIT */
+
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX_VNNI           (12*32+ 4) /* AVX VNNI instructions */
 #define X86_FEATURE_AVX512_BF16                (12*32+ 5) /* AVX512 BFLOAT16 instructions */
 #define X86_FEATURE_AUTOIBRS           (20*32+ 8) /* "" Automatic IBRS */
 #define X86_FEATURE_NO_SMM_CTL_MSR     (20*32+ 9) /* "" SMM_CTL MSR is not present */
 
+#define X86_FEATURE_SBPB               (20*32+27) /* "" Selective Branch Prediction Barrier */
+#define X86_FEATURE_IBPB_BRTYPE                (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */
+#define X86_FEATURE_SRSO_NO            (20*32+29) /* "" CPU is not affected by SRSO */
+
 /*
  * BUG word(s)
  */
 #define X86_BUG_RETBLEED               X86_BUG(27) /* CPU is affected by RETBleed */
 #define X86_BUG_EIBRS_PBRSB            X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
 #define X86_BUG_SMT_RSB                        X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */
+#define X86_BUG_GDS                    X86_BUG(30) /* CPU is affected by Gather Data Sampling */
 
+/* BUG word 2 */
+#define X86_BUG_SRSO                   X86_BUG(1*32 + 0) /* AMD SRSO bug */
+#define X86_BUG_DIV0                   X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */
 #endif /* _ASM_X86_CPUFEATURES_H */
index 117903881fe43eacf5d2167afcfc02461bfffbbd..ce8f50192ae3e46da87fe3a24fc736b3b2fc3b21 100644 (file)
@@ -92,6 +92,7 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
 static __always_inline void arch_exit_to_user_mode(void)
 {
        mds_user_clear_cpu_buffers();
+       amd_clear_divider();
 }
 #define arch_exit_to_user_mode arch_exit_to_user_mode
 
index 0953aa32a324aedbffb8826c0759508a13d52b54..97a3de7892d3ff376c3058d759141b07630c0760 100644 (file)
@@ -21,7 +21,7 @@
 #define FUNCTION_PADDING
 #endif
 
-#if (CONFIG_FUNCTION_ALIGNMENT > 8) && !defined(__DISABLE_EXPORTS) && !defined(BULID_VDSO)
+#if (CONFIG_FUNCTION_ALIGNMENT > 8) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO)
 # define __FUNC_ALIGN          __ALIGN; FUNCTION_PADDING
 #else
 # define __FUNC_ALIGN          __ALIGN
index 88d9ef98e087aff9bfe835457c079a3a0cdc0253..fa83d88e4c99dd61679d02f65cf460fadb2acca4 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/types.h>
 #include <linux/nmi.h>
 #include <linux/msi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/hyperv-tlfs.h>
 #include <asm/nospec-branch.h>
 #include <asm/paravirt.h>
index a00a53e15ab73883e2d289aabe06db84b3208e8a..1d111350197f3169a8eec402d77980dd617c6b95 100644 (file)
@@ -57,6 +57,7 @@
 
 #define MSR_IA32_PRED_CMD              0x00000049 /* Prediction Command */
 #define PRED_CMD_IBPB                  BIT(0)     /* Indirect Branch Prediction Barrier */
+#define PRED_CMD_SBPB                  BIT(7)     /* Selective Branch Prediction Barrier */
 
 #define MSR_PPIN_CTL                   0x0000004e
 #define MSR_PPIN                       0x0000004f
                                                 * Not susceptible to Post-Barrier
                                                 * Return Stack Buffer Predictions.
                                                 */
+#define ARCH_CAP_GDS_CTRL              BIT(25) /*
+                                                * CPU is vulnerable to Gather
+                                                * Data Sampling (GDS) and
+                                                * has controls for mitigation.
+                                                */
+#define ARCH_CAP_GDS_NO                        BIT(26) /*
+                                                * CPU is not vulnerable to Gather
+                                                * Data Sampling (GDS).
+                                                */
 
 #define ARCH_CAP_XAPIC_DISABLE         BIT(21) /*
                                                 * IA32_XAPIC_DISABLE_STATUS MSR
 #define RNGDS_MITG_DIS                 BIT(0)  /* SRBDS support */
 #define RTM_ALLOW                      BIT(1)  /* TSX development mode */
 #define FB_CLEAR_DIS                   BIT(3)  /* CPU Fill buffer clear disable */
+#define GDS_MITG_DIS                   BIT(4)  /* Disable GDS mitigation */
+#define GDS_MITG_LOCKED                        BIT(5)  /* GDS mitigation locked */
 
 #define MSR_IA32_SYSENTER_CS           0x00000174
 #define MSR_IA32_SYSENTER_ESP          0x00000175
index 1a65cf4acb2b93313581497ff27d29ac6cd61365..c55cc243592e946b60e19324cdfc34fe63c2d9ec 100644 (file)
  * eventually turn into it's own annotation.
  */
 .macro VALIDATE_UNRET_END
-#if defined(CONFIG_NOINSTR_VALIDATION) && defined(CONFIG_CPU_UNRET_ENTRY)
+#if defined(CONFIG_NOINSTR_VALIDATION) && \
+       (defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_SRSO))
        ANNOTATE_RETPOLINE_SAFE
        nop
 #endif
 .endm
 
 #ifdef CONFIG_CPU_UNRET_ENTRY
-#define CALL_ZEN_UNTRAIN_RET   "call zen_untrain_ret"
+#define CALL_UNTRAIN_RET       "call entry_untrain_ret"
 #else
-#define CALL_ZEN_UNTRAIN_RET   ""
+#define CALL_UNTRAIN_RET       ""
 #endif
 
 /*
  * return thunk isn't mapped into the userspace tables (then again, AMD
  * typically has NO_MELTDOWN).
  *
- * While zen_untrain_ret() doesn't clobber anything but requires stack,
+ * While retbleed_untrain_ret() doesn't clobber anything but requires stack,
  * entry_ibpb() will clobber AX, CX, DX.
  *
  * As such, this must be placed after every *SWITCH_TO_KERNEL_CR3 at a point
  */
 .macro UNTRAIN_RET
 #if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_IBPB_ENTRY) || \
-       defined(CONFIG_CALL_DEPTH_TRACKING)
+       defined(CONFIG_CALL_DEPTH_TRACKING) || defined(CONFIG_CPU_SRSO)
        VALIDATE_UNRET_END
        ALTERNATIVE_3 "",                                               \
-                     CALL_ZEN_UNTRAIN_RET, X86_FEATURE_UNRET,          \
+                     CALL_UNTRAIN_RET, X86_FEATURE_UNRET,              \
                      "call entry_ibpb", X86_FEATURE_ENTRY_IBPB,        \
                      __stringify(RESET_CALL_DEPTH), X86_FEATURE_CALL_DEPTH
 #endif
 .endm
 
+.macro UNTRAIN_RET_VM
+#if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_IBPB_ENTRY) || \
+       defined(CONFIG_CALL_DEPTH_TRACKING) || defined(CONFIG_CPU_SRSO)
+       VALIDATE_UNRET_END
+       ALTERNATIVE_3 "",                                               \
+                     CALL_UNTRAIN_RET, X86_FEATURE_UNRET,              \
+                     "call entry_ibpb", X86_FEATURE_IBPB_ON_VMEXIT,    \
+                     __stringify(RESET_CALL_DEPTH), X86_FEATURE_CALL_DEPTH
+#endif
+.endm
+
 .macro UNTRAIN_RET_FROM_CALL
 #if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_IBPB_ENTRY) || \
        defined(CONFIG_CALL_DEPTH_TRACKING)
        VALIDATE_UNRET_END
        ALTERNATIVE_3 "",                                               \
-                     CALL_ZEN_UNTRAIN_RET, X86_FEATURE_UNRET,          \
+                     CALL_UNTRAIN_RET, X86_FEATURE_UNRET,              \
                      "call entry_ibpb", X86_FEATURE_ENTRY_IBPB,        \
                      __stringify(RESET_CALL_DEPTH_FROM_CALL), X86_FEATURE_CALL_DEPTH
 #endif
@@ -330,15 +342,24 @@ extern retpoline_thunk_t __x86_indirect_thunk_array[];
 extern retpoline_thunk_t __x86_indirect_call_thunk_array[];
 extern retpoline_thunk_t __x86_indirect_jump_thunk_array[];
 
+#ifdef CONFIG_RETHUNK
 extern void __x86_return_thunk(void);
-extern void zen_untrain_ret(void);
+#else
+static inline void __x86_return_thunk(void) {}
+#endif
+
+extern void retbleed_return_thunk(void);
+extern void srso_return_thunk(void);
+extern void srso_alias_return_thunk(void);
+
+extern void retbleed_untrain_ret(void);
+extern void srso_untrain_ret(void);
+extern void srso_alias_untrain_ret(void);
+
+extern void entry_untrain_ret(void);
 extern void entry_ibpb(void);
 
-#ifdef CONFIG_CALL_THUNKS
 extern void (*x86_return_thunk)(void);
-#else
-#define x86_return_thunk       (&__x86_return_thunk)
-#endif
 
 #ifdef CONFIG_CALL_DEPTH_TRACKING
 extern void __x86_return_skl(void);
@@ -465,9 +486,6 @@ enum ssb_mitigation {
        SPEC_STORE_BYPASS_SECCOMP,
 };
 
-extern char __indirect_thunk_start[];
-extern char __indirect_thunk_end[];
-
 static __always_inline
 void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature)
 {
@@ -479,11 +497,11 @@ void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature)
                : "memory");
 }
 
+extern u64 x86_pred_cmd;
+
 static inline void indirect_branch_prediction_barrier(void)
 {
-       u64 val = PRED_CMD_IBPB;
-
-       alternative_msr_write(MSR_IA32_PRED_CMD, val, X86_FEATURE_USE_IBPB);
+       alternative_msr_write(MSR_IA32_PRED_CMD, x86_pred_cmd, X86_FEATURE_USE_IBPB);
 }
 
 /* The Intel SPEC CTRL MSR base value cache */
index d46300e94f853ae12659b9cf887b0a96444905b6..fd750247ca89149dfc58a8548f9b3e472fb9b14e 100644 (file)
@@ -586,7 +586,6 @@ extern char                 ignore_fpu_irq;
 
 #define HAVE_ARCH_PICK_MMAP_LAYOUT 1
 #define ARCH_HAS_PREFETCHW
-#define ARCH_HAS_SPINLOCK_PREFETCH
 
 #ifdef CONFIG_X86_32
 # define BASE_PREFETCH         ""
@@ -620,11 +619,6 @@ static __always_inline void prefetchw(const void *x)
                          "m" (*(const char *)x));
 }
 
-static inline void spin_lock_prefetch(const void *x)
-{
-       prefetchw(x);
-}
-
 #define TOP_OF_INIT_STACK ((unsigned long)&init_stack + sizeof(init_stack) - \
                           TOP_OF_KERNEL_STACK_PADDING)
 
@@ -682,9 +676,13 @@ extern u16 get_llc_id(unsigned int cpu);
 #ifdef CONFIG_CPU_SUP_AMD
 extern u32 amd_get_nodes_per_socket(void);
 extern u32 amd_get_highest_perf(void);
+extern bool cpu_has_ibpb_brtype_microcode(void);
+extern void amd_clear_divider(void);
 #else
 static inline u32 amd_get_nodes_per_socket(void)       { return 0; }
 static inline u32 amd_get_highest_perf(void)           { return 0; }
+static inline bool cpu_has_ibpb_brtype_microcode(void) { return false; }
+static inline void amd_clear_divider(void)             { }
 #endif
 
 extern unsigned long arch_align_stack(unsigned long sp);
@@ -727,4 +725,6 @@ bool arch_is_platform_page(u64 paddr);
 #define arch_is_platform_page arch_is_platform_page
 #endif
 
+extern bool gds_ucode_mitigated(void);
+
 #endif /* _ASM_X86_PROCESSOR_H */
index 794f696257801b5fbe559105f84add0b449c7ae3..9d6411c6592050e03cc6d66fcffaef2d7511b13a 100644 (file)
@@ -56,7 +56,7 @@
 
 #define GDT_ENTRY_INVALID_SEG  0
 
-#ifdef CONFIG_X86_32
+#if defined(CONFIG_X86_32) && !defined(BUILD_VDSO32_64)
 /*
  * The layout of the per-CPU GDT under Linux:
  *
index 21b542a6866cf74b303f099ce42f6341186e5a27..53369c57751ec8ba18e65b352e3f2632d0f913f8 100644 (file)
@@ -52,6 +52,7 @@ int acpi_lapic;
 int acpi_ioapic;
 int acpi_strict;
 int acpi_disable_cmcff;
+bool acpi_int_src_ovr[NR_IRQS_LEGACY];
 
 /* ACPI SCI override configuration */
 u8 acpi_sci_flags __initdata;
@@ -588,6 +589,9 @@ acpi_parse_int_src_ovr(union acpi_subtable_headers * header,
 
        acpi_table_print_madt_entry(&header->common);
 
+       if (intsrc->source_irq < NR_IRQS_LEGACY)
+               acpi_int_src_ovr[intsrc->source_irq] = true;
+
        if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
                acpi_sci_ioapic_setup(intsrc->source_irq,
                                      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
index 2dcf3a06af0908b6dc67594daff54d7555b9fc83..099d58d02a2624952b34f33c219878ca8ba00e7a 100644 (file)
@@ -687,10 +687,6 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
 
 #ifdef CONFIG_RETHUNK
 
-#ifdef CONFIG_CALL_THUNKS
-void (*x86_return_thunk)(void) __ro_after_init = &__x86_return_thunk;
-#endif
-
 /*
  * Rewrite the compiler generated return thunk tail-calls.
  *
index 26ad7ca423e7cbf2b9d4000ce3621e3e14ff32b9..7eca6a8abbb1c67ddf3f48164f2aec03b194a916 100644 (file)
@@ -73,8 +73,13 @@ static const int amd_erratum_1054[] =
 static const int amd_zenbleed[] =
        AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf),
                           AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf),
+                          AMD_MODEL_RANGE(0x17, 0x90, 0x0, 0x91, 0xf),
                           AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf));
 
+static const int amd_div0[] =
+       AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf),
+                          AMD_MODEL_RANGE(0x17, 0x50, 0x0, 0x5f, 0xf));
+
 static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 {
        int osvw_id = *erratum++;
@@ -1130,6 +1135,11 @@ static void init_amd(struct cpuinfo_x86 *c)
                WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS));
 
        zenbleed_check(c);
+
+       if (cpu_has_amd_erratum(c, amd_div0)) {
+               pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n");
+               setup_force_cpu_bug(X86_BUG_DIV0);
+       }
 }
 
 #ifdef CONFIG_X86_32
@@ -1290,3 +1300,33 @@ void amd_check_microcode(void)
 {
        on_each_cpu(zenbleed_check_cpu, NULL, 1);
 }
+
+bool cpu_has_ibpb_brtype_microcode(void)
+{
+       switch (boot_cpu_data.x86) {
+       /* Zen1/2 IBPB flushes branch type predictions too. */
+       case 0x17:
+               return boot_cpu_has(X86_FEATURE_AMD_IBPB);
+       case 0x19:
+               /* Poke the MSR bit on Zen3/4 to check its presence. */
+               if (!wrmsrl_safe(MSR_IA32_PRED_CMD, PRED_CMD_SBPB)) {
+                       setup_force_cpu_cap(X86_FEATURE_SBPB);
+                       return true;
+               } else {
+                       return false;
+               }
+       default:
+               return false;
+       }
+}
+
+/*
+ * Issue a DIV 0/1 insn to clear any division data from previous DIV
+ * operations.
+ */
+void noinstr amd_clear_divider(void)
+{
+       asm volatile(ALTERNATIVE("", "div %2\n\t", X86_BUG_DIV0)
+                    :: "a" (0), "d" (0), "r" (1));
+}
+EXPORT_SYMBOL_GPL(amd_clear_divider);
index 95507448e781401de6ca092f908fa58820558e94..f081d26616ac1ce9aebf720ce3430bece3a02025 100644 (file)
@@ -47,6 +47,8 @@ static void __init taa_select_mitigation(void);
 static void __init mmio_select_mitigation(void);
 static void __init srbds_select_mitigation(void);
 static void __init l1d_flush_select_mitigation(void);
+static void __init srso_select_mitigation(void);
+static void __init gds_select_mitigation(void);
 
 /* The base value of the SPEC_CTRL MSR without task-specific bits set */
 u64 x86_spec_ctrl_base;
@@ -56,8 +58,13 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_base);
 DEFINE_PER_CPU(u64, x86_spec_ctrl_current);
 EXPORT_SYMBOL_GPL(x86_spec_ctrl_current);
 
+u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB;
+EXPORT_SYMBOL_GPL(x86_pred_cmd);
+
 static DEFINE_MUTEX(spec_ctrl_mutex);
 
+void (*x86_return_thunk)(void) __ro_after_init = &__x86_return_thunk;
+
 /* Update SPEC_CTRL MSR and its cached copy unconditionally */
 static void update_spec_ctrl(u64 val)
 {
@@ -160,6 +167,13 @@ void __init cpu_select_mitigations(void)
        md_clear_select_mitigation();
        srbds_select_mitigation();
        l1d_flush_select_mitigation();
+
+       /*
+        * srso_select_mitigation() depends and must run after
+        * retbleed_select_mitigation().
+        */
+       srso_select_mitigation();
+       gds_select_mitigation();
 }
 
 /*
@@ -645,6 +659,149 @@ static int __init l1d_flush_parse_cmdline(char *str)
 }
 early_param("l1d_flush", l1d_flush_parse_cmdline);
 
+#undef pr_fmt
+#define pr_fmt(fmt)    "GDS: " fmt
+
+enum gds_mitigations {
+       GDS_MITIGATION_OFF,
+       GDS_MITIGATION_UCODE_NEEDED,
+       GDS_MITIGATION_FORCE,
+       GDS_MITIGATION_FULL,
+       GDS_MITIGATION_FULL_LOCKED,
+       GDS_MITIGATION_HYPERVISOR,
+};
+
+#if IS_ENABLED(CONFIG_GDS_FORCE_MITIGATION)
+static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FORCE;
+#else
+static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FULL;
+#endif
+
+static const char * const gds_strings[] = {
+       [GDS_MITIGATION_OFF]            = "Vulnerable",
+       [GDS_MITIGATION_UCODE_NEEDED]   = "Vulnerable: No microcode",
+       [GDS_MITIGATION_FORCE]          = "Mitigation: AVX disabled, no microcode",
+       [GDS_MITIGATION_FULL]           = "Mitigation: Microcode",
+       [GDS_MITIGATION_FULL_LOCKED]    = "Mitigation: Microcode (locked)",
+       [GDS_MITIGATION_HYPERVISOR]     = "Unknown: Dependent on hypervisor status",
+};
+
+bool gds_ucode_mitigated(void)
+{
+       return (gds_mitigation == GDS_MITIGATION_FULL ||
+               gds_mitigation == GDS_MITIGATION_FULL_LOCKED);
+}
+EXPORT_SYMBOL_GPL(gds_ucode_mitigated);
+
+void update_gds_msr(void)
+{
+       u64 mcu_ctrl_after;
+       u64 mcu_ctrl;
+
+       switch (gds_mitigation) {
+       case GDS_MITIGATION_OFF:
+               rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+               mcu_ctrl |= GDS_MITG_DIS;
+               break;
+       case GDS_MITIGATION_FULL_LOCKED:
+               /*
+                * The LOCKED state comes from the boot CPU. APs might not have
+                * the same state. Make sure the mitigation is enabled on all
+                * CPUs.
+                */
+       case GDS_MITIGATION_FULL:
+               rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+               mcu_ctrl &= ~GDS_MITG_DIS;
+               break;
+       case GDS_MITIGATION_FORCE:
+       case GDS_MITIGATION_UCODE_NEEDED:
+       case GDS_MITIGATION_HYPERVISOR:
+               return;
+       };
+
+       wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+
+       /*
+        * Check to make sure that the WRMSR value was not ignored. Writes to
+        * GDS_MITG_DIS will be ignored if this processor is locked but the boot
+        * processor was not.
+        */
+       rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl_after);
+       WARN_ON_ONCE(mcu_ctrl != mcu_ctrl_after);
+}
+
+static void __init gds_select_mitigation(void)
+{
+       u64 mcu_ctrl;
+
+       if (!boot_cpu_has_bug(X86_BUG_GDS))
+               return;
+
+       if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
+               gds_mitigation = GDS_MITIGATION_HYPERVISOR;
+               goto out;
+       }
+
+       if (cpu_mitigations_off())
+               gds_mitigation = GDS_MITIGATION_OFF;
+       /* Will verify below that mitigation _can_ be disabled */
+
+       /* No microcode */
+       if (!(x86_read_arch_cap_msr() & ARCH_CAP_GDS_CTRL)) {
+               if (gds_mitigation == GDS_MITIGATION_FORCE) {
+                       /*
+                        * This only needs to be done on the boot CPU so do it
+                        * here rather than in update_gds_msr()
+                        */
+                       setup_clear_cpu_cap(X86_FEATURE_AVX);
+                       pr_warn("Microcode update needed! Disabling AVX as mitigation.\n");
+               } else {
+                       gds_mitigation = GDS_MITIGATION_UCODE_NEEDED;
+               }
+               goto out;
+       }
+
+       /* Microcode has mitigation, use it */
+       if (gds_mitigation == GDS_MITIGATION_FORCE)
+               gds_mitigation = GDS_MITIGATION_FULL;
+
+       rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+       if (mcu_ctrl & GDS_MITG_LOCKED) {
+               if (gds_mitigation == GDS_MITIGATION_OFF)
+                       pr_warn("Mitigation locked. Disable failed.\n");
+
+               /*
+                * The mitigation is selected from the boot CPU. All other CPUs
+                * _should_ have the same state. If the boot CPU isn't locked
+                * but others are then update_gds_msr() will WARN() of the state
+                * mismatch. If the boot CPU is locked update_gds_msr() will
+                * ensure the other CPUs have the mitigation enabled.
+                */
+               gds_mitigation = GDS_MITIGATION_FULL_LOCKED;
+       }
+
+       update_gds_msr();
+out:
+       pr_info("%s\n", gds_strings[gds_mitigation]);
+}
+
+static int __init gds_parse_cmdline(char *str)
+{
+       if (!str)
+               return -EINVAL;
+
+       if (!boot_cpu_has_bug(X86_BUG_GDS))
+               return 0;
+
+       if (!strcmp(str, "off"))
+               gds_mitigation = GDS_MITIGATION_OFF;
+       else if (!strcmp(str, "force"))
+               gds_mitigation = GDS_MITIGATION_FORCE;
+
+       return 0;
+}
+early_param("gather_data_sampling", gds_parse_cmdline);
+
 #undef pr_fmt
 #define pr_fmt(fmt)     "Spectre V1 : " fmt
 
@@ -885,6 +1042,9 @@ do_cmd_auto:
                setup_force_cpu_cap(X86_FEATURE_RETHUNK);
                setup_force_cpu_cap(X86_FEATURE_UNRET);
 
+               if (IS_ENABLED(CONFIG_RETHUNK))
+                       x86_return_thunk = retbleed_return_thunk;
+
                if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
                    boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
                        pr_err(RETBLEED_UNTRAIN_MSG);
@@ -894,6 +1054,7 @@ do_cmd_auto:
 
        case RETBLEED_MITIGATION_IBPB:
                setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB);
+               setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT);
                mitigate_smt = true;
                break;
 
@@ -2187,6 +2348,170 @@ static int __init l1tf_cmdline(char *str)
 }
 early_param("l1tf", l1tf_cmdline);
 
+#undef pr_fmt
+#define pr_fmt(fmt)    "Speculative Return Stack Overflow: " fmt
+
+enum srso_mitigation {
+       SRSO_MITIGATION_NONE,
+       SRSO_MITIGATION_MICROCODE,
+       SRSO_MITIGATION_SAFE_RET,
+       SRSO_MITIGATION_IBPB,
+       SRSO_MITIGATION_IBPB_ON_VMEXIT,
+};
+
+enum srso_mitigation_cmd {
+       SRSO_CMD_OFF,
+       SRSO_CMD_MICROCODE,
+       SRSO_CMD_SAFE_RET,
+       SRSO_CMD_IBPB,
+       SRSO_CMD_IBPB_ON_VMEXIT,
+};
+
+static const char * const srso_strings[] = {
+       [SRSO_MITIGATION_NONE]           = "Vulnerable",
+       [SRSO_MITIGATION_MICROCODE]      = "Mitigation: microcode",
+       [SRSO_MITIGATION_SAFE_RET]       = "Mitigation: safe RET",
+       [SRSO_MITIGATION_IBPB]           = "Mitigation: IBPB",
+       [SRSO_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT only"
+};
+
+static enum srso_mitigation srso_mitigation __ro_after_init = SRSO_MITIGATION_NONE;
+static enum srso_mitigation_cmd srso_cmd __ro_after_init = SRSO_CMD_SAFE_RET;
+
+static int __init srso_parse_cmdline(char *str)
+{
+       if (!str)
+               return -EINVAL;
+
+       if (!strcmp(str, "off"))
+               srso_cmd = SRSO_CMD_OFF;
+       else if (!strcmp(str, "microcode"))
+               srso_cmd = SRSO_CMD_MICROCODE;
+       else if (!strcmp(str, "safe-ret"))
+               srso_cmd = SRSO_CMD_SAFE_RET;
+       else if (!strcmp(str, "ibpb"))
+               srso_cmd = SRSO_CMD_IBPB;
+       else if (!strcmp(str, "ibpb-vmexit"))
+               srso_cmd = SRSO_CMD_IBPB_ON_VMEXIT;
+       else
+               pr_err("Ignoring unknown SRSO option (%s).", str);
+
+       return 0;
+}
+early_param("spec_rstack_overflow", srso_parse_cmdline);
+
+#define SRSO_NOTICE "WARNING: See https://kernel.org/doc/html/latest/admin-guide/hw-vuln/srso.html for mitigation options."
+
+static void __init srso_select_mitigation(void)
+{
+       bool has_microcode;
+
+       if (!boot_cpu_has_bug(X86_BUG_SRSO) || cpu_mitigations_off())
+               goto pred_cmd;
+
+       /*
+        * The first check is for the kernel running as a guest in order
+        * for guests to verify whether IBPB is a viable mitigation.
+        */
+       has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) || cpu_has_ibpb_brtype_microcode();
+       if (!has_microcode) {
+               pr_warn("IBPB-extending microcode not applied!\n");
+               pr_warn(SRSO_NOTICE);
+       } else {
+               /*
+                * Enable the synthetic (even if in a real CPUID leaf)
+                * flags for guests.
+                */
+               setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
+
+               /*
+                * Zen1/2 with SMT off aren't vulnerable after the right
+                * IBPB microcode has been applied.
+                */
+               if (boot_cpu_data.x86 < 0x19 && !cpu_smt_possible()) {
+                       setup_force_cpu_cap(X86_FEATURE_SRSO_NO);
+                       return;
+               }
+       }
+
+       if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB) {
+               if (has_microcode) {
+                       pr_err("Retbleed IBPB mitigation enabled, using same for SRSO\n");
+                       srso_mitigation = SRSO_MITIGATION_IBPB;
+                       goto pred_cmd;
+               }
+       }
+
+       switch (srso_cmd) {
+       case SRSO_CMD_OFF:
+               return;
+
+       case SRSO_CMD_MICROCODE:
+               if (has_microcode) {
+                       srso_mitigation = SRSO_MITIGATION_MICROCODE;
+                       pr_warn(SRSO_NOTICE);
+               }
+               break;
+
+       case SRSO_CMD_SAFE_RET:
+               if (IS_ENABLED(CONFIG_CPU_SRSO)) {
+                       /*
+                        * Enable the return thunk for generated code
+                        * like ftrace, static_call, etc.
+                        */
+                       setup_force_cpu_cap(X86_FEATURE_RETHUNK);
+                       setup_force_cpu_cap(X86_FEATURE_UNRET);
+
+                       if (boot_cpu_data.x86 == 0x19) {
+                               setup_force_cpu_cap(X86_FEATURE_SRSO_ALIAS);
+                               x86_return_thunk = srso_alias_return_thunk;
+                       } else {
+                               setup_force_cpu_cap(X86_FEATURE_SRSO);
+                               x86_return_thunk = srso_return_thunk;
+                       }
+                       srso_mitigation = SRSO_MITIGATION_SAFE_RET;
+               } else {
+                       pr_err("WARNING: kernel not compiled with CPU_SRSO.\n");
+                       goto pred_cmd;
+               }
+               break;
+
+       case SRSO_CMD_IBPB:
+               if (IS_ENABLED(CONFIG_CPU_IBPB_ENTRY)) {
+                       if (has_microcode) {
+                               setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB);
+                               srso_mitigation = SRSO_MITIGATION_IBPB;
+                       }
+               } else {
+                       pr_err("WARNING: kernel not compiled with CPU_IBPB_ENTRY.\n");
+                       goto pred_cmd;
+               }
+               break;
+
+       case SRSO_CMD_IBPB_ON_VMEXIT:
+               if (IS_ENABLED(CONFIG_CPU_SRSO)) {
+                       if (!boot_cpu_has(X86_FEATURE_ENTRY_IBPB) && has_microcode) {
+                               setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT);
+                               srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT;
+                       }
+               } else {
+                       pr_err("WARNING: kernel not compiled with CPU_SRSO.\n");
+                       goto pred_cmd;
+                }
+               break;
+
+       default:
+               break;
+       }
+
+       pr_info("%s%s\n", srso_strings[srso_mitigation], (has_microcode ? "" : ", no microcode"));
+
+pred_cmd:
+       if ((boot_cpu_has(X86_FEATURE_SRSO_NO) || srso_cmd == SRSO_CMD_OFF) &&
+            boot_cpu_has(X86_FEATURE_SBPB))
+               x86_pred_cmd = PRED_CMD_SBPB;
+}
+
 #undef pr_fmt
 #define pr_fmt(fmt) fmt
 
@@ -2385,6 +2710,21 @@ static ssize_t retbleed_show_state(char *buf)
        return sysfs_emit(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
 }
 
+static ssize_t srso_show_state(char *buf)
+{
+       if (boot_cpu_has(X86_FEATURE_SRSO_NO))
+               return sysfs_emit(buf, "Mitigation: SMT disabled\n");
+
+       return sysfs_emit(buf, "%s%s\n",
+                         srso_strings[srso_mitigation],
+                         (cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode"));
+}
+
+static ssize_t gds_show_state(char *buf)
+{
+       return sysfs_emit(buf, "%s\n", gds_strings[gds_mitigation]);
+}
+
 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
                               char *buf, unsigned int bug)
 {
@@ -2434,6 +2774,12 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
        case X86_BUG_RETBLEED:
                return retbleed_show_state(buf);
 
+       case X86_BUG_SRSO:
+               return srso_show_state(buf);
+
+       case X86_BUG_GDS:
+               return gds_show_state(buf);
+
        default:
                break;
        }
@@ -2498,4 +2844,14 @@ ssize_t cpu_show_retbleed(struct device *dev, struct device_attribute *attr, cha
 {
        return cpu_show_common(dev, attr, buf, X86_BUG_RETBLEED);
 }
+
+ssize_t cpu_show_spec_rstack_overflow(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return cpu_show_common(dev, attr, buf, X86_BUG_SRSO);
+}
+
+ssize_t cpu_show_gds(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return cpu_show_common(dev, attr, buf, X86_BUG_GDS);
+}
 #endif
index 0ba1067f4e5f15bf16b518bf71bfa4f7676b0190..e3a65e9fc750db893798562a83ac0f5b1b0e9e0f 100644 (file)
@@ -1250,6 +1250,10 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
 #define RETBLEED       BIT(3)
 /* CPU is affected by SMT (cross-thread) return predictions */
 #define SMT_RSB                BIT(4)
+/* CPU is affected by SRSO */
+#define SRSO           BIT(5)
+/* CPU is affected by GDS */
+#define GDS            BIT(6)
 
 static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
        VULNBL_INTEL_STEPPINGS(IVYBRIDGE,       X86_STEPPING_ANY,               SRBDS),
@@ -1262,27 +1266,30 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
        VULNBL_INTEL_STEPPINGS(BROADWELL_X,     X86_STEPPING_ANY,               MMIO),
        VULNBL_INTEL_STEPPINGS(BROADWELL,       X86_STEPPING_ANY,               SRBDS),
        VULNBL_INTEL_STEPPINGS(SKYLAKE_L,       X86_STEPPING_ANY,               SRBDS | MMIO | RETBLEED),
-       VULNBL_INTEL_STEPPINGS(SKYLAKE_X,       X86_STEPPING_ANY,               MMIO | RETBLEED),
+       VULNBL_INTEL_STEPPINGS(SKYLAKE_X,       X86_STEPPING_ANY,               MMIO | RETBLEED | GDS),
        VULNBL_INTEL_STEPPINGS(SKYLAKE,         X86_STEPPING_ANY,               SRBDS | MMIO | RETBLEED),
-       VULNBL_INTEL_STEPPINGS(KABYLAKE_L,      X86_STEPPING_ANY,               SRBDS | MMIO | RETBLEED),
-       VULNBL_INTEL_STEPPINGS(KABYLAKE,        X86_STEPPING_ANY,               SRBDS | MMIO | RETBLEED),
+       VULNBL_INTEL_STEPPINGS(KABYLAKE_L,      X86_STEPPING_ANY,               SRBDS | MMIO | RETBLEED | GDS),
+       VULNBL_INTEL_STEPPINGS(KABYLAKE,        X86_STEPPING_ANY,               SRBDS | MMIO | RETBLEED | GDS),
        VULNBL_INTEL_STEPPINGS(CANNONLAKE_L,    X86_STEPPING_ANY,               RETBLEED),
-       VULNBL_INTEL_STEPPINGS(ICELAKE_L,       X86_STEPPING_ANY,               MMIO | MMIO_SBDS | RETBLEED),
-       VULNBL_INTEL_STEPPINGS(ICELAKE_D,       X86_STEPPING_ANY,               MMIO),
-       VULNBL_INTEL_STEPPINGS(ICELAKE_X,       X86_STEPPING_ANY,               MMIO),
-       VULNBL_INTEL_STEPPINGS(COMETLAKE,       X86_STEPPING_ANY,               MMIO | MMIO_SBDS | RETBLEED),
+       VULNBL_INTEL_STEPPINGS(ICELAKE_L,       X86_STEPPING_ANY,               MMIO | MMIO_SBDS | RETBLEED | GDS),
+       VULNBL_INTEL_STEPPINGS(ICELAKE_D,       X86_STEPPING_ANY,               MMIO | GDS),
+       VULNBL_INTEL_STEPPINGS(ICELAKE_X,       X86_STEPPING_ANY,               MMIO | GDS),
+       VULNBL_INTEL_STEPPINGS(COMETLAKE,       X86_STEPPING_ANY,               MMIO | MMIO_SBDS | RETBLEED | GDS),
        VULNBL_INTEL_STEPPINGS(COMETLAKE_L,     X86_STEPPINGS(0x0, 0x0),        MMIO | RETBLEED),
-       VULNBL_INTEL_STEPPINGS(COMETLAKE_L,     X86_STEPPING_ANY,               MMIO | MMIO_SBDS | RETBLEED),
+       VULNBL_INTEL_STEPPINGS(COMETLAKE_L,     X86_STEPPING_ANY,               MMIO | MMIO_SBDS | RETBLEED | GDS),
+       VULNBL_INTEL_STEPPINGS(TIGERLAKE_L,     X86_STEPPING_ANY,               GDS),
+       VULNBL_INTEL_STEPPINGS(TIGERLAKE,       X86_STEPPING_ANY,               GDS),
        VULNBL_INTEL_STEPPINGS(LAKEFIELD,       X86_STEPPING_ANY,               MMIO | MMIO_SBDS | RETBLEED),
-       VULNBL_INTEL_STEPPINGS(ROCKETLAKE,      X86_STEPPING_ANY,               MMIO | RETBLEED),
+       VULNBL_INTEL_STEPPINGS(ROCKETLAKE,      X86_STEPPING_ANY,               MMIO | RETBLEED | GDS),
        VULNBL_INTEL_STEPPINGS(ATOM_TREMONT,    X86_STEPPING_ANY,               MMIO | MMIO_SBDS),
        VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D,  X86_STEPPING_ANY,               MMIO),
        VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L,  X86_STEPPING_ANY,               MMIO | MMIO_SBDS),
 
        VULNBL_AMD(0x15, RETBLEED),
        VULNBL_AMD(0x16, RETBLEED),
-       VULNBL_AMD(0x17, RETBLEED | SMT_RSB),
+       VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO),
        VULNBL_HYGON(0x18, RETBLEED | SMT_RSB),
+       VULNBL_AMD(0x19, SRSO),
        {}
 };
 
@@ -1406,6 +1413,21 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
        if (cpu_matches(cpu_vuln_blacklist, SMT_RSB))
                setup_force_cpu_bug(X86_BUG_SMT_RSB);
 
+       if (!cpu_has(c, X86_FEATURE_SRSO_NO)) {
+               if (cpu_matches(cpu_vuln_blacklist, SRSO))
+                       setup_force_cpu_bug(X86_BUG_SRSO);
+       }
+
+       /*
+        * Check if CPU is vulnerable to GDS. If running in a virtual machine on
+        * an affected processor, the VMM may have disabled the use of GATHER by
+        * disabling AVX2. The only way to do this in HW is to clear XCR0[2],
+        * which means that AVX will be disabled.
+        */
+       if (cpu_matches(cpu_vuln_blacklist, GDS) && !(ia32_cap & ARCH_CAP_GDS_NO) &&
+           boot_cpu_has(X86_FEATURE_AVX))
+               setup_force_cpu_bug(X86_BUG_GDS);
+
        if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
                return;
 
@@ -1962,6 +1984,8 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
        validate_apic_and_package_id(c);
        x86_spec_ctrl_setup_ap();
        update_srbds_msr();
+       if (boot_cpu_has_bug(X86_BUG_GDS))
+               update_gds_msr();
 
        tsx_ap_init();
 }
index 1c44630d47891c5fe0ac5313a221fbd7721ab1e3..1dcd7d4e38ef17189f42e81b6842f2dd07448405 100644 (file)
@@ -83,6 +83,7 @@ void cpu_select_mitigations(void);
 
 extern void x86_spec_ctrl_setup_ap(void);
 extern void update_srbds_msr(void);
+extern void update_gds_msr(void);
 
 extern enum spectre_v2_mitigation spectre_v2_enabled;
 
index 57b0037d0a996d28236d1a523bd73ec1e4224cd8..517821b48391aadf63b49d42783dd7f09f5f2bfa 100644 (file)
@@ -226,7 +226,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src, u8 *real)
 }
 
 /* Check whether insn is indirect jump */
-static int __insn_is_indirect_jump(struct insn *insn)
+static int insn_is_indirect_jump(struct insn *insn)
 {
        return ((insn->opcode.bytes[0] == 0xff &&
                (X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
@@ -260,26 +260,6 @@ static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
        return (start <= target && target <= start + len);
 }
 
-static int insn_is_indirect_jump(struct insn *insn)
-{
-       int ret = __insn_is_indirect_jump(insn);
-
-#ifdef CONFIG_RETPOLINE
-       /*
-        * Jump to x86_indirect_thunk_* is treated as an indirect jump.
-        * Note that even with CONFIG_RETPOLINE=y, the kernel compiled with
-        * older gcc may use indirect jump. So we add this check instead of
-        * replace indirect-jump check.
-        */
-       if (!ret)
-               ret = insn_jump_into_range(insn,
-                               (unsigned long)__indirect_thunk_start,
-                               (unsigned long)__indirect_thunk_end -
-                               (unsigned long)__indirect_thunk_start);
-#endif
-       return ret;
-}
-
 /* Decode whole function to ensure any instructions don't jump into target */
 static int can_optimize(unsigned long paddr)
 {
@@ -334,9 +314,21 @@ static int can_optimize(unsigned long paddr)
                /* Recover address */
                insn.kaddr = (void *)addr;
                insn.next_byte = (void *)(addr + insn.length);
-               /* Check any instructions don't jump into target */
-               if (insn_is_indirect_jump(&insn) ||
-                   insn_jump_into_range(&insn, paddr + INT3_INSN_SIZE,
+               /*
+                * Check any instructions don't jump into target, indirectly or
+                * directly.
+                *
+                * The indirect case is present to handle a code with jump
+                * tables. When the kernel uses retpolines, the check should in
+                * theory additionally look for jumps to indirect thunks.
+                * However, the kernel built with retpolines or IBT has jump
+                * tables disabled so the check can be skipped altogether.
+                */
+               if (!IS_ENABLED(CONFIG_RETPOLINE) &&
+                   !IS_ENABLED(CONFIG_X86_KERNEL_IBT) &&
+                   insn_is_indirect_jump(&insn))
+                       return 0;
+               if (insn_jump_into_range(&insn, paddr + INT3_INSN_SIZE,
                                         DISP32_SIZE))
                        return 0;
                addr += insn.length;
index b70670a985978313d787f466e56534a4fb06a365..77a9316da43573de5f1a7a2e6f220a1190600862 100644 (file)
@@ -186,6 +186,19 @@ EXPORT_SYMBOL_GPL(arch_static_call_transform);
  */
 bool __static_call_fixup(void *tramp, u8 op, void *dest)
 {
+       unsigned long addr = (unsigned long)tramp;
+       /*
+        * Not all .return_sites are a static_call trampoline (most are not).
+        * Check if the 3 bytes after the return are still kernel text, if not,
+        * then this definitely is not a trampoline and we need not worry
+        * further.
+        *
+        * This avoids the memcmp() below tripping over pagefaults etc..
+        */
+       if (((addr >> PAGE_SHIFT) != ((addr + 7) >> PAGE_SHIFT)) &&
+           !kernel_text_address(addr + 7))
+               return false;
+
        if (memcmp(tramp+5, tramp_ud, 3)) {
                /* Not a trampoline site, not our problem. */
                return false;
index 03c885d3640fbe6b626a6fe14cabdf31c9e01dcb..83d41c2601d7b5b5ca8714b71c3c0224e077401f 100644 (file)
@@ -133,14 +133,26 @@ SECTIONS
                KPROBES_TEXT
                SOFTIRQENTRY_TEXT
 #ifdef CONFIG_RETPOLINE
-               __indirect_thunk_start = .;
-               *(.text.__x86.*)
-               __indirect_thunk_end = .;
+               *(.text..__x86.indirect_thunk)
+               *(.text..__x86.return_thunk)
 #endif
                STATIC_CALL_TEXT
 
                ALIGN_ENTRY_TEXT_BEGIN
+#ifdef CONFIG_CPU_SRSO
+               *(.text..__x86.rethunk_untrain)
+#endif
+
                ENTRY_TEXT
+
+#ifdef CONFIG_CPU_SRSO
+               /*
+                * See the comment above srso_alias_untrain_ret()'s
+                * definition.
+                */
+               . = srso_alias_untrain_ret | (1 << 2) | (1 << 8) | (1 << 14) | (1 << 20);
+               *(.text..__x86.rethunk_safe)
+#endif
                ALIGN_ENTRY_TEXT_END
                *(.gnu.warning)
 
@@ -509,7 +521,24 @@ INIT_PER_CPU(irq_stack_backing_store);
 #endif
 
 #ifdef CONFIG_RETHUNK
-. = ASSERT((__x86_return_thunk & 0x3f) == 0, "__x86_return_thunk not cacheline-aligned");
+. = ASSERT((retbleed_return_thunk & 0x3f) == 0, "retbleed_return_thunk not cacheline-aligned");
+. = ASSERT((srso_safe_ret & 0x3f) == 0, "srso_safe_ret not cacheline-aligned");
+#endif
+
+#ifdef CONFIG_CPU_SRSO
+/*
+ * GNU ld cannot do XOR until 2.41.
+ * https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=f6f78318fca803c4907fb8d7f6ded8295f1947b1
+ *
+ * LLVM lld cannot do XOR until lld-17.
+ * https://github.com/llvm/llvm-project/commit/fae96104d4378166cbe5c875ef8ed808a356f3fb
+ *
+ * Instead do: (A | B) - (A & B) in order to compute the XOR
+ * of the two function addresses:
+ */
+. = ASSERT(((ABSOLUTE(srso_alias_untrain_ret) | srso_alias_safe_ret) -
+               (ABSOLUTE(srso_alias_untrain_ret) & srso_alias_safe_ret)) == ((1 << 2) | (1 << 8) | (1 << 14) | (1 << 20)),
+               "SRSO function pair won't alias");
 #endif
 
 #endif /* CONFIG_X86_64 */
index 7f4d13383cf2582e14a573d445e0501ec8ba9169..d3432687c9e6315d0a521a5babce201a527a3a0b 100644 (file)
@@ -729,6 +729,9 @@ void kvm_set_cpu_caps(void)
                F(NULL_SEL_CLR_BASE) | F(AUTOIBRS) | 0 /* PrefetchCtlMsr */
        );
 
+       if (cpu_feature_enabled(X86_FEATURE_SRSO_NO))
+               kvm_cpu_cap_set(X86_FEATURE_SRSO_NO);
+
        kvm_cpu_cap_init_kvm_defined(CPUID_8000_0022_EAX,
                F(PERFMON_V2)
        );
index 07756b7348ae8edec8c5f0e0f41070eb2998a7e8..d3aec1f2cad20f0507a02b3987b42c33c4419bef 100644 (file)
@@ -2417,15 +2417,18 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm)
         */
        memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs));
 
-       vcpu->arch.regs[VCPU_REGS_RAX] = ghcb_get_rax_if_valid(ghcb);
-       vcpu->arch.regs[VCPU_REGS_RBX] = ghcb_get_rbx_if_valid(ghcb);
-       vcpu->arch.regs[VCPU_REGS_RCX] = ghcb_get_rcx_if_valid(ghcb);
-       vcpu->arch.regs[VCPU_REGS_RDX] = ghcb_get_rdx_if_valid(ghcb);
-       vcpu->arch.regs[VCPU_REGS_RSI] = ghcb_get_rsi_if_valid(ghcb);
+       BUILD_BUG_ON(sizeof(svm->sev_es.valid_bitmap) != sizeof(ghcb->save.valid_bitmap));
+       memcpy(&svm->sev_es.valid_bitmap, &ghcb->save.valid_bitmap, sizeof(ghcb->save.valid_bitmap));
 
-       svm->vmcb->save.cpl = ghcb_get_cpl_if_valid(ghcb);
+       vcpu->arch.regs[VCPU_REGS_RAX] = kvm_ghcb_get_rax_if_valid(svm, ghcb);
+       vcpu->arch.regs[VCPU_REGS_RBX] = kvm_ghcb_get_rbx_if_valid(svm, ghcb);
+       vcpu->arch.regs[VCPU_REGS_RCX] = kvm_ghcb_get_rcx_if_valid(svm, ghcb);
+       vcpu->arch.regs[VCPU_REGS_RDX] = kvm_ghcb_get_rdx_if_valid(svm, ghcb);
+       vcpu->arch.regs[VCPU_REGS_RSI] = kvm_ghcb_get_rsi_if_valid(svm, ghcb);
 
-       if (ghcb_xcr0_is_valid(ghcb)) {
+       svm->vmcb->save.cpl = kvm_ghcb_get_cpl_if_valid(svm, ghcb);
+
+       if (kvm_ghcb_xcr0_is_valid(svm)) {
                vcpu->arch.xcr0 = ghcb_get_xcr0(ghcb);
                kvm_update_cpuid_runtime(vcpu);
        }
@@ -2436,84 +2439,88 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm)
        control->exit_code_hi = upper_32_bits(exit_code);
        control->exit_info_1 = ghcb_get_sw_exit_info_1(ghcb);
        control->exit_info_2 = ghcb_get_sw_exit_info_2(ghcb);
+       svm->sev_es.sw_scratch = kvm_ghcb_get_sw_scratch_if_valid(svm, ghcb);
 
        /* Clear the valid entries fields */
        memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap));
 }
 
+static u64 kvm_ghcb_get_sw_exit_code(struct vmcb_control_area *control)
+{
+       return (((u64)control->exit_code_hi) << 32) | control->exit_code;
+}
+
 static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
 {
-       struct kvm_vcpu *vcpu;
-       struct ghcb *ghcb;
+       struct vmcb_control_area *control = &svm->vmcb->control;
+       struct kvm_vcpu *vcpu = &svm->vcpu;
        u64 exit_code;
        u64 reason;
 
-       ghcb = svm->sev_es.ghcb;
-
        /*
         * Retrieve the exit code now even though it may not be marked valid
         * as it could help with debugging.
         */
-       exit_code = ghcb_get_sw_exit_code(ghcb);
+       exit_code = kvm_ghcb_get_sw_exit_code(control);
 
        /* Only GHCB Usage code 0 is supported */
-       if (ghcb->ghcb_usage) {
+       if (svm->sev_es.ghcb->ghcb_usage) {
                reason = GHCB_ERR_INVALID_USAGE;
                goto vmgexit_err;
        }
 
        reason = GHCB_ERR_MISSING_INPUT;
 
-       if (!ghcb_sw_exit_code_is_valid(ghcb) ||
-           !ghcb_sw_exit_info_1_is_valid(ghcb) ||
-           !ghcb_sw_exit_info_2_is_valid(ghcb))
+       if (!kvm_ghcb_sw_exit_code_is_valid(svm) ||
+           !kvm_ghcb_sw_exit_info_1_is_valid(svm) ||
+           !kvm_ghcb_sw_exit_info_2_is_valid(svm))
                goto vmgexit_err;
 
-       switch (ghcb_get_sw_exit_code(ghcb)) {
+       switch (exit_code) {
        case SVM_EXIT_READ_DR7:
                break;
        case SVM_EXIT_WRITE_DR7:
-               if (!ghcb_rax_is_valid(ghcb))
+               if (!kvm_ghcb_rax_is_valid(svm))
                        goto vmgexit_err;
                break;
        case SVM_EXIT_RDTSC:
                break;
        case SVM_EXIT_RDPMC:
-               if (!ghcb_rcx_is_valid(ghcb))
+               if (!kvm_ghcb_rcx_is_valid(svm))
                        goto vmgexit_err;
                break;
        case SVM_EXIT_CPUID:
-               if (!ghcb_rax_is_valid(ghcb) ||
-                   !ghcb_rcx_is_valid(ghcb))
+               if (!kvm_ghcb_rax_is_valid(svm) ||
+                   !kvm_ghcb_rcx_is_valid(svm))
                        goto vmgexit_err;
-               if (ghcb_get_rax(ghcb) == 0xd)
-                       if (!ghcb_xcr0_is_valid(ghcb))
+               if (vcpu->arch.regs[VCPU_REGS_RAX] == 0xd)
+                       if (!kvm_ghcb_xcr0_is_valid(svm))
                                goto vmgexit_err;
                break;
        case SVM_EXIT_INVD:
                break;
        case SVM_EXIT_IOIO:
-               if (ghcb_get_sw_exit_info_1(ghcb) & SVM_IOIO_STR_MASK) {
-                       if (!ghcb_sw_scratch_is_valid(ghcb))
+               if (control->exit_info_1 & SVM_IOIO_STR_MASK) {
+                       if (!kvm_ghcb_sw_scratch_is_valid(svm))
                                goto vmgexit_err;
                } else {
-                       if (!(ghcb_get_sw_exit_info_1(ghcb) & SVM_IOIO_TYPE_MASK))
-                               if (!ghcb_rax_is_valid(ghcb))
+                       if (!(control->exit_info_1 & SVM_IOIO_TYPE_MASK))
+                               if (!kvm_ghcb_rax_is_valid(svm))
                                        goto vmgexit_err;
                }
                break;
        case SVM_EXIT_MSR:
-               if (!ghcb_rcx_is_valid(ghcb))
+               if (!kvm_ghcb_rcx_is_valid(svm))
                        goto vmgexit_err;
-               if (ghcb_get_sw_exit_info_1(ghcb)) {
-                       if (!ghcb_rax_is_valid(ghcb) ||
-                           !ghcb_rdx_is_valid(ghcb))
+               if (control->exit_info_1) {
+                       if (!kvm_ghcb_rax_is_valid(svm) ||
+                           !kvm_ghcb_rdx_is_valid(svm))
                                goto vmgexit_err;
                }
                break;
        case SVM_EXIT_VMMCALL:
-               if (!ghcb_rax_is_valid(ghcb) ||
-                   !ghcb_cpl_is_valid(ghcb))
+               if (!kvm_ghcb_rax_is_valid(svm) ||
+                   !kvm_ghcb_cpl_is_valid(svm))
                        goto vmgexit_err;
                break;
        case SVM_EXIT_RDTSCP:
@@ -2521,19 +2528,19 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
        case SVM_EXIT_WBINVD:
                break;
        case SVM_EXIT_MONITOR:
-               if (!ghcb_rax_is_valid(ghcb) ||
-                   !ghcb_rcx_is_valid(ghcb) ||
-                   !ghcb_rdx_is_valid(ghcb))
+               if (!kvm_ghcb_rax_is_valid(svm) ||
+                   !kvm_ghcb_rcx_is_valid(svm) ||
+                   !kvm_ghcb_rdx_is_valid(svm))
                        goto vmgexit_err;
                break;
        case SVM_EXIT_MWAIT:
-               if (!ghcb_rax_is_valid(ghcb) ||
-                   !ghcb_rcx_is_valid(ghcb))
+               if (!kvm_ghcb_rax_is_valid(svm) ||
+                   !kvm_ghcb_rcx_is_valid(svm))
                        goto vmgexit_err;
                break;
        case SVM_VMGEXIT_MMIO_READ:
        case SVM_VMGEXIT_MMIO_WRITE:
-               if (!ghcb_sw_scratch_is_valid(ghcb))
+               if (!kvm_ghcb_sw_scratch_is_valid(svm))
                        goto vmgexit_err;
                break;
        case SVM_VMGEXIT_NMI_COMPLETE:
@@ -2549,11 +2556,9 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
        return 0;
 
 vmgexit_err:
-       vcpu = &svm->vcpu;
-
        if (reason == GHCB_ERR_INVALID_USAGE) {
                vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n",
-                           ghcb->ghcb_usage);
+                           svm->sev_es.ghcb->ghcb_usage);
        } else if (reason == GHCB_ERR_INVALID_EVENT) {
                vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n",
                            exit_code);
@@ -2563,11 +2568,8 @@ vmgexit_err:
                dump_ghcb(svm);
        }
 
-       /* Clear the valid entries fields */
-       memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap));
-
-       ghcb_set_sw_exit_info_1(ghcb, 2);
-       ghcb_set_sw_exit_info_2(ghcb, reason);
+       ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
+       ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, reason);
 
        /* Resume the guest to "return" the error code. */
        return 1;
@@ -2586,7 +2588,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
                 */
                if (svm->sev_es.ghcb_sa_sync) {
                        kvm_write_guest(svm->vcpu.kvm,
-                                       ghcb_get_sw_scratch(svm->sev_es.ghcb),
+                                       svm->sev_es.sw_scratch,
                                        svm->sev_es.ghcb_sa,
                                        svm->sev_es.ghcb_sa_len);
                        svm->sev_es.ghcb_sa_sync = false;
@@ -2632,12 +2634,11 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu)
 static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
 {
        struct vmcb_control_area *control = &svm->vmcb->control;
-       struct ghcb *ghcb = svm->sev_es.ghcb;
        u64 ghcb_scratch_beg, ghcb_scratch_end;
        u64 scratch_gpa_beg, scratch_gpa_end;
        void *scratch_va;
 
-       scratch_gpa_beg = ghcb_get_sw_scratch(ghcb);
+       scratch_gpa_beg = svm->sev_es.sw_scratch;
        if (!scratch_gpa_beg) {
                pr_err("vmgexit: scratch gpa not provided\n");
                goto e_scratch;
@@ -2708,8 +2709,8 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
        return 0;
 
 e_scratch:
-       ghcb_set_sw_exit_info_1(ghcb, 2);
-       ghcb_set_sw_exit_info_2(ghcb, GHCB_ERR_INVALID_SCRATCH_AREA);
+       ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
+       ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_SCRATCH_AREA);
 
        return 1;
 }
@@ -2822,7 +2823,6 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
        struct vcpu_svm *svm = to_svm(vcpu);
        struct vmcb_control_area *control = &svm->vmcb->control;
        u64 ghcb_gpa, exit_code;
-       struct ghcb *ghcb;
        int ret;
 
        /* Validate the GHCB */
@@ -2847,20 +2847,18 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
        }
 
        svm->sev_es.ghcb = svm->sev_es.ghcb_map.hva;
-       ghcb = svm->sev_es.ghcb_map.hva;
 
-       trace_kvm_vmgexit_enter(vcpu->vcpu_id, ghcb);
-
-       exit_code = ghcb_get_sw_exit_code(ghcb);
+       trace_kvm_vmgexit_enter(vcpu->vcpu_id, svm->sev_es.ghcb);
 
+       sev_es_sync_from_ghcb(svm);
        ret = sev_es_validate_vmgexit(svm);
        if (ret)
                return ret;
 
-       sev_es_sync_from_ghcb(svm);
-       ghcb_set_sw_exit_info_1(ghcb, 0);
-       ghcb_set_sw_exit_info_2(ghcb, 0);
+       ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 0);
+       ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, 0);
 
+       exit_code = kvm_ghcb_get_sw_exit_code(control);
        switch (exit_code) {
        case SVM_VMGEXIT_MMIO_READ:
                ret = setup_vmgexit_scratch(svm, true, control->exit_info_2);
@@ -2898,13 +2896,13 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
                        break;
                case 1:
                        /* Get AP jump table address */
-                       ghcb_set_sw_exit_info_2(ghcb, sev->ap_jump_table);
+                       ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, sev->ap_jump_table);
                        break;
                default:
                        pr_err("svm: vmgexit: unsupported AP jump table request - exit_info_1=%#llx\n",
                               control->exit_info_1);
-                       ghcb_set_sw_exit_info_1(ghcb, 2);
-                       ghcb_set_sw_exit_info_2(ghcb, GHCB_ERR_INVALID_INPUT);
+                       ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
+                       ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT);
                }
 
                ret = 1;
index 956726d867aafcd0b0f2917505aa155f04284622..d4bfdc607fe7f3257c9c68a4ee34c6a2c3a7e5c9 100644 (file)
@@ -1498,7 +1498,9 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
        if (sd->current_vmcb != svm->vmcb) {
                sd->current_vmcb = svm->vmcb;
-               indirect_branch_prediction_barrier();
+
+               if (!cpu_feature_enabled(X86_FEATURE_IBPB_ON_VMEXIT))
+                       indirect_branch_prediction_barrier();
        }
        if (kvm_vcpu_apicv_active(vcpu))
                avic_vcpu_load(vcpu, cpu);
@@ -4004,6 +4006,8 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in
 
        guest_state_enter_irqoff();
 
+       amd_clear_divider();
+
        if (sev_es_guest(vcpu->kvm))
                __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted);
        else
index 18af7e712a5ae73d93cff78255eeb3fc2d0c5bb1..8239c8de45acfd3c6117acd8dbe5c14d2b9039d7 100644 (file)
@@ -190,10 +190,12 @@ struct vcpu_sev_es_state {
        /* SEV-ES support */
        struct sev_es_save_area *vmsa;
        struct ghcb *ghcb;
+       u8 valid_bitmap[16];
        struct kvm_host_map ghcb_map;
        bool received_first_sipi;
 
        /* SEV-ES scratch area support */
+       u64 sw_scratch;
        void *ghcb_sa;
        u32 ghcb_sa_len;
        bool ghcb_sa_sync;
@@ -744,4 +746,28 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm);
 void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
 void __svm_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
 
+#define DEFINE_KVM_GHCB_ACCESSORS(field)                                               \
+       static __always_inline bool kvm_ghcb_##field##_is_valid(const struct vcpu_svm *svm) \
+       {                                                                       \
+               return test_bit(GHCB_BITMAP_IDX(field),                         \
+                               (unsigned long *)&svm->sev_es.valid_bitmap);    \
+       }                                                                       \
+                                                                               \
+       static __always_inline u64 kvm_ghcb_get_##field##_if_valid(struct vcpu_svm *svm, struct ghcb *ghcb) \
+       {                                                                       \
+               return kvm_ghcb_##field##_is_valid(svm) ? ghcb->save.field : 0; \
+       }                                                                       \
+
+DEFINE_KVM_GHCB_ACCESSORS(cpl)
+DEFINE_KVM_GHCB_ACCESSORS(rax)
+DEFINE_KVM_GHCB_ACCESSORS(rcx)
+DEFINE_KVM_GHCB_ACCESSORS(rdx)
+DEFINE_KVM_GHCB_ACCESSORS(rbx)
+DEFINE_KVM_GHCB_ACCESSORS(rsi)
+DEFINE_KVM_GHCB_ACCESSORS(sw_exit_code)
+DEFINE_KVM_GHCB_ACCESSORS(sw_exit_info_1)
+DEFINE_KVM_GHCB_ACCESSORS(sw_exit_info_2)
+DEFINE_KVM_GHCB_ACCESSORS(sw_scratch)
+DEFINE_KVM_GHCB_ACCESSORS(xcr0)
+
 #endif
index 8e8295e774f0f3aa2b08a58948535f4caff2d4ac..ef2ebabb059c8cdf2f88eb7b98682e29940e4dd8 100644 (file)
@@ -222,7 +222,7 @@ SYM_FUNC_START(__svm_vcpu_run)
         * because interrupt handlers won't sanitize 'ret' if the return is
         * from the kernel.
         */
-       UNTRAIN_RET
+       UNTRAIN_RET_VM
 
        /*
         * Clear all general purpose registers except RSP and RAX to prevent
@@ -359,7 +359,7 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
         * because interrupt handlers won't sanitize RET if the return is
         * from the kernel.
         */
-       UNTRAIN_RET
+       UNTRAIN_RET_VM
 
        /* "Pop" @spec_ctrl_intercepted.  */
        pop %_ASM_BX
index 278dbd37dab244676abb4d5e9d5323236c57823f..c381770bcbf13509379d7218c794b5c49628844b 100644 (file)
@@ -1616,7 +1616,7 @@ static bool kvm_is_immutable_feature_msr(u32 msr)
         ARCH_CAP_SKIP_VMENTRY_L1DFLUSH | ARCH_CAP_SSB_NO | ARCH_CAP_MDS_NO | \
         ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \
         ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \
-        ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO)
+        ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO)
 
 static u64 kvm_get_arch_capabilities(void)
 {
@@ -1673,6 +1673,9 @@ static u64 kvm_get_arch_capabilities(void)
                 */
        }
 
+       if (!boot_cpu_has_bug(X86_BUG_GDS) || gds_ucode_mitigated())
+               data |= ARCH_CAP_GDS_NO;
+
        return data;
 }
 
index 3fd066d42ec056e26154db0823789d1e4b81a73a..cd86aeb5fdd3eac07cf3f7872d3e22b771967f54 100644 (file)
@@ -11,8 +11,9 @@
 #include <asm/unwind_hints.h>
 #include <asm/percpu.h>
 #include <asm/frame.h>
+#include <asm/nops.h>
 
-       .section .text.__x86.indirect_thunk
+       .section .text..__x86.indirect_thunk
 
 
 .macro POLINE reg
@@ -131,36 +132,107 @@ SYM_CODE_END(__x86_indirect_jump_thunk_array)
  */
 #ifdef CONFIG_RETHUNK
 
-       .section .text.__x86.return_thunk
+/*
+ * srso_alias_untrain_ret() and srso_alias_safe_ret() are placed at
+ * special addresses:
+ *
+ * - srso_alias_untrain_ret() is 2M aligned
+ * - srso_alias_safe_ret() is also in the same 2M page but bits 2, 8, 14
+ * and 20 in its virtual address are set (while those bits in the
+ * srso_alias_untrain_ret() function are cleared).
+ *
+ * This guarantees that those two addresses will alias in the branch
+ * target buffer of Zen3/4 generations, leading to any potential
+ * poisoned entries at that BTB slot to get evicted.
+ *
+ * As a result, srso_alias_safe_ret() becomes a safe return.
+ */
+#ifdef CONFIG_CPU_SRSO
+       .section .text..__x86.rethunk_untrain
+
+SYM_START(srso_alias_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
+       UNWIND_HINT_FUNC
+       ANNOTATE_NOENDBR
+       ASM_NOP2
+       lfence
+       jmp srso_alias_return_thunk
+SYM_FUNC_END(srso_alias_untrain_ret)
+__EXPORT_THUNK(srso_alias_untrain_ret)
+
+       .section .text..__x86.rethunk_safe
+#else
+/* dummy definition for alternatives */
+SYM_START(srso_alias_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
+       ANNOTATE_UNRET_SAFE
+       ret
+       int3
+SYM_FUNC_END(srso_alias_untrain_ret)
+#endif
+
+SYM_START(srso_alias_safe_ret, SYM_L_GLOBAL, SYM_A_NONE)
+       lea 8(%_ASM_SP), %_ASM_SP
+       UNWIND_HINT_FUNC
+       ANNOTATE_UNRET_SAFE
+       ret
+       int3
+SYM_FUNC_END(srso_alias_safe_ret)
+
+       .section .text..__x86.return_thunk
+
+SYM_CODE_START(srso_alias_return_thunk)
+       UNWIND_HINT_FUNC
+       ANNOTATE_NOENDBR
+       call srso_alias_safe_ret
+       ud2
+SYM_CODE_END(srso_alias_return_thunk)
+
+/*
+ * Some generic notes on the untraining sequences:
+ *
+ * They are interchangeable when it comes to flushing potentially wrong
+ * RET predictions from the BTB.
+ *
+ * The SRSO Zen1/2 (MOVABS) untraining sequence is longer than the
+ * Retbleed sequence because the return sequence done there
+ * (srso_safe_ret()) is longer and the return sequence must fully nest
+ * (end before) the untraining sequence. Therefore, the untraining
+ * sequence must fully overlap the return sequence.
+ *
+ * Regarding alignment - the instructions which need to be untrained,
+ * must all start at a cacheline boundary for Zen1/2 generations. That
+ * is, instruction sequences starting at srso_safe_ret() and
+ * the respective instruction sequences at retbleed_return_thunk()
+ * must start at a cacheline boundary.
+ */
 
 /*
  * Safety details here pertain to the AMD Zen{1,2} microarchitecture:
- * 1) The RET at __x86_return_thunk must be on a 64 byte boundary, for
+ * 1) The RET at retbleed_return_thunk must be on a 64 byte boundary, for
  *    alignment within the BTB.
- * 2) The instruction at zen_untrain_ret must contain, and not
+ * 2) The instruction at retbleed_untrain_ret must contain, and not
  *    end with, the 0xc3 byte of the RET.
  * 3) STIBP must be enabled, or SMT disabled, to prevent the sibling thread
  *    from re-poisioning the BTB prediction.
  */
        .align 64
-       .skip 64 - (__x86_return_thunk - zen_untrain_ret), 0xcc
-SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
+       .skip 64 - (retbleed_return_thunk - retbleed_untrain_ret), 0xcc
+SYM_START(retbleed_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
        ANNOTATE_NOENDBR
        /*
-        * As executed from zen_untrain_ret, this is:
+        * As executed from retbleed_untrain_ret, this is:
         *
         *   TEST $0xcc, %bl
         *   LFENCE
-        *   JMP __x86_return_thunk
+        *   JMP retbleed_return_thunk
         *
         * Executing the TEST instruction has a side effect of evicting any BTB
         * prediction (potentially attacker controlled) attached to the RET, as
-        * __x86_return_thunk + 1 isn't an instruction boundary at the moment.
+        * retbleed_return_thunk + 1 isn't an instruction boundary at the moment.
         */
        .byte   0xf6
 
        /*
-        * As executed from __x86_return_thunk, this is a plain RET.
+        * As executed from retbleed_return_thunk, this is a plain RET.
         *
         * As part of the TEST above, RET is the ModRM byte, and INT3 the imm8.
         *
@@ -172,13 +244,13 @@ SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
         * With SMT enabled and STIBP active, a sibling thread cannot poison
         * RET's prediction to a type of its choice, but can evict the
         * prediction due to competitive sharing. If the prediction is
-        * evicted, __x86_return_thunk will suffer Straight Line Speculation
+        * evicted, retbleed_return_thunk will suffer Straight Line Speculation
         * which will be contained safely by the INT3.
         */
-SYM_INNER_LABEL(__x86_return_thunk, SYM_L_GLOBAL)
+SYM_INNER_LABEL(retbleed_return_thunk, SYM_L_GLOBAL)
        ret
        int3
-SYM_CODE_END(__x86_return_thunk)
+SYM_CODE_END(retbleed_return_thunk)
 
        /*
         * Ensure the TEST decoding / BTB invalidation is complete.
@@ -189,11 +261,67 @@ SYM_CODE_END(__x86_return_thunk)
         * Jump back and execute the RET in the middle of the TEST instruction.
         * INT3 is for SLS protection.
         */
-       jmp __x86_return_thunk
+       jmp retbleed_return_thunk
        int3
-SYM_FUNC_END(zen_untrain_ret)
-__EXPORT_THUNK(zen_untrain_ret)
+SYM_FUNC_END(retbleed_untrain_ret)
+__EXPORT_THUNK(retbleed_untrain_ret)
 
+/*
+ * SRSO untraining sequence for Zen1/2, similar to retbleed_untrain_ret()
+ * above. On kernel entry, srso_untrain_ret() is executed which is a
+ *
+ * movabs $0xccccc30824648d48,%rax
+ *
+ * and when the return thunk executes the inner label srso_safe_ret()
+ * later, it is a stack manipulation and a RET which is mispredicted and
+ * thus a "safe" one to use.
+ */
+       .align 64
+       .skip 64 - (srso_safe_ret - srso_untrain_ret), 0xcc
+SYM_START(srso_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
+       ANNOTATE_NOENDBR
+       .byte 0x48, 0xb8
+
+/*
+ * This forces the function return instruction to speculate into a trap
+ * (UD2 in srso_return_thunk() below).  This RET will then mispredict
+ * and execution will continue at the return site read from the top of
+ * the stack.
+ */
+SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL)
+       lea 8(%_ASM_SP), %_ASM_SP
+       ret
+       int3
+       int3
+       /* end of movabs */
+       lfence
+       call srso_safe_ret
+       ud2
+SYM_CODE_END(srso_safe_ret)
+SYM_FUNC_END(srso_untrain_ret)
+__EXPORT_THUNK(srso_untrain_ret)
+
+SYM_CODE_START(srso_return_thunk)
+       UNWIND_HINT_FUNC
+       ANNOTATE_NOENDBR
+       call srso_safe_ret
+       ud2
+SYM_CODE_END(srso_return_thunk)
+
+SYM_FUNC_START(entry_untrain_ret)
+       ALTERNATIVE_2 "jmp retbleed_untrain_ret", \
+                     "jmp srso_untrain_ret", X86_FEATURE_SRSO, \
+                     "jmp srso_alias_untrain_ret", X86_FEATURE_SRSO_ALIAS
+SYM_FUNC_END(entry_untrain_ret)
+__EXPORT_THUNK(entry_untrain_ret)
+
+SYM_CODE_START(__x86_return_thunk)
+       UNWIND_HINT_FUNC
+       ANNOTATE_NOENDBR
+       ANNOTATE_UNRET_SAFE
+       ret
+       int3
+SYM_CODE_END(__x86_return_thunk)
 EXPORT_SYMBOL(__x86_return_thunk)
 
 #endif /* CONFIG_RETHUNK */
index 93b658248d013c5a64c441fbcd5110945501211e..a3864e2167a80416901e4b63e3e1714877299651 100644 (file)
@@ -79,7 +79,7 @@
 #ifdef CONFIG_ACPI
 #include <linux/acpi.h>
 #include <asm/acpi.h>
-#include <acpi/pdc_intel.h>
+#include <acpi/proc_cap_intel.h>
 #include <acpi/processor.h>
 #include <xen/interface/platform.h>
 #endif
@@ -288,17 +288,17 @@ static bool __init xen_check_mwait(void)
 
        native_cpuid(&ax, &bx, &cx, &dx);
 
-       /* Ask the Hypervisor whether to clear ACPI_PDC_C_C2C3_FFH. If so,
+       /* Ask the Hypervisor whether to clear ACPI_PROC_CAP_C_C2C3_FFH. If so,
         * don't expose MWAIT_LEAF and let ACPI pick the IOPORT version of C3.
         */
        buf[0] = ACPI_PDC_REVISION_ID;
        buf[1] = 1;
-       buf[2] = (ACPI_PDC_C_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_SWSMP);
+       buf[2] = (ACPI_PROC_CAP_C_CAPABILITY_SMP | ACPI_PROC_CAP_EST_CAPABILITY_SWSMP);
 
        set_xen_guest_handle(op.u.set_pminfo.pdc, buf);
 
        if ((HYPERVISOR_platform_op(&op) == 0) &&
-           (buf[2] & (ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH))) {
+           (buf[2] & (ACPI_PROC_CAP_C_C1_FFH | ACPI_PROC_CAP_C_C2C3_FFH))) {
                cpuid_leaf5_ecx_val = cx;
                cpuid_leaf5_edx_val = dx;
        }
index fc49be622e05b159e3a3a5fb5f717383cd325c93..9faafcd10e1775dd124a2b15e653e46ac2790847 100644 (file)
@@ -136,7 +136,9 @@ static void blkg_free_workfn(struct work_struct *work)
                        blkcg_policy[i]->pd_free_fn(blkg->pd[i]);
        if (blkg->parent)
                blkg_put(blkg->parent);
+       spin_lock_irq(&q->queue_lock);
        list_del_init(&blkg->q_node);
+       spin_unlock_irq(&q->queue_lock);
        mutex_unlock(&q->blkcg_mutex);
 
        blk_put_queue(q);
index 90de50082146a93fbf77e8191a55ffa4d12e3c13..9866468c72a2a68d531aa809d1638e8fc15284a1 100644 (file)
@@ -722,14 +722,9 @@ void submit_bio_noacct(struct bio *bio)
        struct block_device *bdev = bio->bi_bdev;
        struct request_queue *q = bdev_get_queue(bdev);
        blk_status_t status = BLK_STS_IOERR;
-       struct blk_plug *plug;
 
        might_sleep();
 
-       plug = blk_mq_plug(bio);
-       if (plug && plug->nowait)
-               bio->bi_opf |= REQ_NOWAIT;
-
        /*
         * For a REQ_NOWAIT based request, return -EOPNOTSUPP
         * if queue does not support NOWAIT.
@@ -1059,7 +1054,6 @@ void blk_start_plug_nr_ios(struct blk_plug *plug, unsigned short nr_ios)
        plug->rq_count = 0;
        plug->multiple_queues = false;
        plug->has_elevator = false;
-       plug->nowait = false;
        INIT_LIST_HEAD(&plug->cb_list);
 
        /*
index ad9844c5b40cb8f491ff9f6647d1f67af007a39e..e6468eab2681e9f827e9b86b3b21d24f6a6fe0a5 100644 (file)
@@ -78,7 +78,7 @@ static struct blk_crypto_fallback_keyslot {
        struct crypto_skcipher *tfms[BLK_ENCRYPTION_MODE_MAX];
 } *blk_crypto_keyslots;
 
-static struct blk_crypto_profile blk_crypto_fallback_profile;
+static struct blk_crypto_profile *blk_crypto_fallback_profile;
 static struct workqueue_struct *blk_crypto_wq;
 static mempool_t *blk_crypto_bounce_page_pool;
 static struct bio_set crypto_bio_split;
@@ -292,7 +292,7 @@ static bool blk_crypto_fallback_encrypt_bio(struct bio **bio_ptr)
         * Get a blk-crypto-fallback keyslot that contains a crypto_skcipher for
         * this bio's algorithm and key.
         */
-       blk_st = blk_crypto_get_keyslot(&blk_crypto_fallback_profile,
+       blk_st = blk_crypto_get_keyslot(blk_crypto_fallback_profile,
                                        bc->bc_key, &slot);
        if (blk_st != BLK_STS_OK) {
                src_bio->bi_status = blk_st;
@@ -395,7 +395,7 @@ static void blk_crypto_fallback_decrypt_bio(struct work_struct *work)
         * Get a blk-crypto-fallback keyslot that contains a crypto_skcipher for
         * this bio's algorithm and key.
         */
-       blk_st = blk_crypto_get_keyslot(&blk_crypto_fallback_profile,
+       blk_st = blk_crypto_get_keyslot(blk_crypto_fallback_profile,
                                        bc->bc_key, &slot);
        if (blk_st != BLK_STS_OK) {
                bio->bi_status = blk_st;
@@ -499,7 +499,7 @@ bool blk_crypto_fallback_bio_prep(struct bio **bio_ptr)
                return false;
        }
 
-       if (!__blk_crypto_cfg_supported(&blk_crypto_fallback_profile,
+       if (!__blk_crypto_cfg_supported(blk_crypto_fallback_profile,
                                        &bc->bc_key->crypto_cfg)) {
                bio->bi_status = BLK_STS_NOTSUPP;
                return false;
@@ -526,7 +526,7 @@ bool blk_crypto_fallback_bio_prep(struct bio **bio_ptr)
 
 int blk_crypto_fallback_evict_key(const struct blk_crypto_key *key)
 {
-       return __blk_crypto_evict_key(&blk_crypto_fallback_profile, key);
+       return __blk_crypto_evict_key(blk_crypto_fallback_profile, key);
 }
 
 static bool blk_crypto_fallback_inited;
@@ -534,7 +534,6 @@ static int blk_crypto_fallback_init(void)
 {
        int i;
        int err;
-       struct blk_crypto_profile *profile = &blk_crypto_fallback_profile;
 
        if (blk_crypto_fallback_inited)
                return 0;
@@ -545,18 +544,27 @@ static int blk_crypto_fallback_init(void)
        if (err)
                goto out;
 
-       err = blk_crypto_profile_init(profile, blk_crypto_num_keyslots);
-       if (err)
+       /* Dynamic allocation is needed because of lockdep_register_key(). */
+       blk_crypto_fallback_profile =
+               kzalloc(sizeof(*blk_crypto_fallback_profile), GFP_KERNEL);
+       if (!blk_crypto_fallback_profile) {
+               err = -ENOMEM;
                goto fail_free_bioset;
+       }
+
+       err = blk_crypto_profile_init(blk_crypto_fallback_profile,
+                                     blk_crypto_num_keyslots);
+       if (err)
+               goto fail_free_profile;
        err = -ENOMEM;
 
-       profile->ll_ops = blk_crypto_fallback_ll_ops;
-       profile->max_dun_bytes_supported = BLK_CRYPTO_MAX_IV_SIZE;
+       blk_crypto_fallback_profile->ll_ops = blk_crypto_fallback_ll_ops;
+       blk_crypto_fallback_profile->max_dun_bytes_supported = BLK_CRYPTO_MAX_IV_SIZE;
 
        /* All blk-crypto modes have a crypto API fallback. */
        for (i = 0; i < BLK_ENCRYPTION_MODE_MAX; i++)
-               profile->modes_supported[i] = 0xFFFFFFFF;
-       profile->modes_supported[BLK_ENCRYPTION_MODE_INVALID] = 0;
+               blk_crypto_fallback_profile->modes_supported[i] = 0xFFFFFFFF;
+       blk_crypto_fallback_profile->modes_supported[BLK_ENCRYPTION_MODE_INVALID] = 0;
 
        blk_crypto_wq = alloc_workqueue("blk_crypto_wq",
                                        WQ_UNBOUND | WQ_HIGHPRI |
@@ -597,7 +605,9 @@ fail_free_keyslots:
 fail_free_wq:
        destroy_workqueue(blk_crypto_wq);
 fail_destroy_profile:
-       blk_crypto_profile_destroy(profile);
+       blk_crypto_profile_destroy(blk_crypto_fallback_profile);
+fail_free_profile:
+       kfree(blk_crypto_fallback_profile);
 fail_free_bioset:
        bioset_exit(&crypto_bio_split);
 out:
index dd64e2066f012400703b364e78eb0c04fdb31c5e..089fcb9cfce37011f4cf6ec1f86ba36853fed381 100644 (file)
@@ -3301,11 +3301,12 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
        if (qos[QOS_MIN] > qos[QOS_MAX])
                goto einval;
 
-       if (enable) {
+       if (enable && !ioc->enabled) {
                blk_stat_enable_accounting(disk->queue);
                blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue);
                ioc->enabled = true;
-       } else {
+       } else if (!enable && ioc->enabled) {
+               blk_stat_disable_accounting(disk->queue);
                blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue);
                ioc->enabled = false;
        }
index b04ff6f56926f80d6528235366fe81cee51f6bf1..953f08354c8c36c61b972d1ffe0ede740af2687a 100644 (file)
@@ -681,6 +681,21 @@ out_queue_exit:
 }
 EXPORT_SYMBOL_GPL(blk_mq_alloc_request_hctx);
 
+static void blk_mq_finish_request(struct request *rq)
+{
+       struct request_queue *q = rq->q;
+
+       if (rq->rq_flags & RQF_USE_SCHED) {
+               q->elevator->type->ops.finish_request(rq);
+               /*
+                * For postflush request that may need to be
+                * completed twice, we should clear this flag
+                * to avoid double finish_request() on the rq.
+                */
+               rq->rq_flags &= ~RQF_USE_SCHED;
+       }
+}
+
 static void __blk_mq_free_request(struct request *rq)
 {
        struct request_queue *q = rq->q;
@@ -707,9 +722,7 @@ void blk_mq_free_request(struct request *rq)
 {
        struct request_queue *q = rq->q;
 
-       if ((rq->rq_flags & RQF_USE_SCHED) &&
-           q->elevator->type->ops.finish_request)
-               q->elevator->type->ops.finish_request(rq);
+       blk_mq_finish_request(rq);
 
        if (unlikely(laptop_mode && !blk_rq_is_passthrough(rq)))
                laptop_io_completion(q->disk->bdi);
@@ -1020,6 +1033,8 @@ inline void __blk_mq_end_request(struct request *rq, blk_status_t error)
        if (blk_mq_need_time_stamp(rq))
                __blk_mq_end_request_acct(rq, ktime_get_ns());
 
+       blk_mq_finish_request(rq);
+
        if (rq->end_io) {
                rq_qos_done(rq->q, rq);
                if (rq->end_io(rq, error) == RQ_END_IO_FREE)
@@ -1074,6 +1089,8 @@ void blk_mq_end_request_batch(struct io_comp_batch *iob)
                if (iob->need_ts)
                        __blk_mq_end_request_acct(rq, now);
 
+               blk_mq_finish_request(rq);
+
                rq_qos_done(rq->q, rq);
 
                /*
index 8400e303fbcbd6d4e0e4371aa990e021bedb24a6..5ff093cb3cf8f5221b01e7bd57229e7582d8d3b9 100644 (file)
@@ -499,6 +499,9 @@ void elv_unregister_queue(struct request_queue *q)
 
 int elv_register(struct elevator_type *e)
 {
+       /* finish request is mandatory */
+       if (WARN_ON_ONCE(!e->ops.finish_request))
+               return -EINVAL;
        /* insert_requests and dispatch_request are mandatory */
        if (WARN_ON_ONCE(!e->ops.insert_requests || !e->ops.dispatch_request))
                return -EINVAL;
index a286bf3325c5d84bf8d0e388f560f584ec57283c..838ffada53413f4fd40ff154c24b1d7af593a48a 100644 (file)
@@ -358,13 +358,14 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb,
                task_io_account_write(bio->bi_iter.bi_size);
        }
 
+       if (iocb->ki_flags & IOCB_NOWAIT)
+               bio->bi_opf |= REQ_NOWAIT;
+
        if (iocb->ki_flags & IOCB_HIPRI) {
-               bio->bi_opf |= REQ_POLLED | REQ_NOWAIT;
+               bio->bi_opf |= REQ_POLLED;
                submit_bio(bio);
                WRITE_ONCE(iocb->private, bio);
        } else {
-               if (iocb->ki_flags & IOCB_NOWAIT)
-                       bio->bi_opf |= REQ_NOWAIT;
                submit_bio(bio);
        }
        return -EIOCBQUEUED;
index 06b15b9f661ca0f97b8d1b569becbbeec857eb43..10efb56d8b48132b45b2d5b0758334aff1e4d359 100644 (file)
@@ -1241,6 +1241,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
                                return -ENOMEM;
                }
 
+               rsgl->sgl.need_unpin =
+                       iov_iter_extract_will_pin(&msg->msg_iter);
                rsgl->sgl.sgt.sgl = rsgl->sgl.sgl;
                rsgl->sgl.sgt.nents = 0;
                rsgl->sgl.sgt.orig_nents = 0;
@@ -1255,8 +1257,6 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
                }
 
                sg_mark_end(rsgl->sgl.sgt.sgl + rsgl->sgl.sgt.nents - 1);
-               rsgl->sgl.need_unpin =
-                       iov_iter_extract_will_pin(&msg->msg_iter);
 
                /* chain the new scatterlist with previous one */
                if (areq->last_rsgl)
index 52b339aefadcae0dd01f5d0d5d1a20aec44c1412..9967fcfa27eca1b5815532690e2b802ecdc478ab 100644 (file)
@@ -173,6 +173,9 @@ static void internal_free_pages_locked(struct ivpu_bo *bo)
 {
        unsigned int i, npages = bo->base.size >> PAGE_SHIFT;
 
+       if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED)
+               set_pages_array_wb(bo->pages, bo->base.size >> PAGE_SHIFT);
+
        for (i = 0; i < npages; i++)
                put_page(bo->pages[i]);
 
@@ -587,6 +590,11 @@ ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 fla
        if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED)
                drm_clflush_pages(bo->pages, bo->base.size >> PAGE_SHIFT);
 
+       if (bo->flags & DRM_IVPU_BO_WC)
+               set_pages_array_wc(bo->pages, bo->base.size >> PAGE_SHIFT);
+       else if (bo->flags & DRM_IVPU_BO_UNCACHED)
+               set_pages_array_uc(bo->pages, bo->base.size >> PAGE_SHIFT);
+
        prot = ivpu_bo_pgprot(bo, PAGE_KERNEL);
        bo->kvaddr = vmap(bo->pages, bo->base.size >> PAGE_SHIFT, VM_MAP, prot);
        if (!bo->kvaddr) {
index cfbc92da426fa8e2a203728c7c998af0e4bbd04e..388abd40024ba40be0afab2693ed8e1ce5a1368b 100644 (file)
@@ -392,18 +392,31 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
                                   struct qaic_manage_trans_dma_xfer *in_trans,
                                   struct ioctl_resources *resources, struct dma_xfer *xfer)
 {
+       u64 xfer_start_addr, remaining, end, total;
        unsigned long need_pages;
        struct page **page_list;
        unsigned long nr_pages;
        struct sg_table *sgt;
-       u64 xfer_start_addr;
        int ret;
        int i;
 
-       xfer_start_addr = in_trans->addr + resources->xferred_dma_size;
+       if (check_add_overflow(in_trans->addr, resources->xferred_dma_size, &xfer_start_addr))
+               return -EINVAL;
 
-       need_pages = DIV_ROUND_UP(in_trans->size + offset_in_page(xfer_start_addr) -
-                                 resources->xferred_dma_size, PAGE_SIZE);
+       if (in_trans->size < resources->xferred_dma_size)
+               return -EINVAL;
+       remaining = in_trans->size - resources->xferred_dma_size;
+       if (remaining == 0)
+               return 0;
+
+       if (check_add_overflow(xfer_start_addr, remaining, &end))
+               return -EINVAL;
+
+       total = remaining + offset_in_page(xfer_start_addr);
+       if (total >= SIZE_MAX)
+               return -EINVAL;
+
+       need_pages = DIV_ROUND_UP(total, PAGE_SIZE);
 
        nr_pages = need_pages;
 
@@ -435,7 +448,7 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
 
        ret = sg_alloc_table_from_pages(sgt, page_list, nr_pages,
                                        offset_in_page(xfer_start_addr),
-                                       in_trans->size - resources->xferred_dma_size, GFP_KERNEL);
+                                       remaining, GFP_KERNEL);
        if (ret) {
                ret = -ENOMEM;
                goto free_sgt;
@@ -566,9 +579,6 @@ static int encode_dma(struct qaic_device *qdev, void *trans, struct wrapper_list
            QAIC_MANAGE_EXT_MSG_LENGTH)
                return -ENOMEM;
 
-       if (in_trans->addr + in_trans->size < in_trans->addr || !in_trans->size)
-               return -EINVAL;
-
        xfer = kmalloc(sizeof(*xfer), GFP_KERNEL);
        if (!xfer)
                return -ENOMEM;
index e9a1cb779b3056aedb3cb561926d5472aab56d11..6b6d981a71be7a1e6ed5c08b97de1357ba5cbe01 100644 (file)
@@ -1021,6 +1021,7 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
        bo->dbc = dbc;
        srcu_read_unlock(&dbc->ch_lock, rcu_id);
        drm_gem_object_put(obj);
+       kfree(slice_ent);
        srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
        srcu_read_unlock(&usr->qddev_lock, usr_rcu_id);
 
index 1ace70b831cdfecd4a2f87fe8fa57788776541bd..225dc6818751ef598a9ad293a44bef15ffef5a0c 100644 (file)
@@ -34,7 +34,7 @@ MODULE_LICENSE("GPL");
 
 static int acpi_ac_add(struct acpi_device *device);
 static void acpi_ac_remove(struct acpi_device *device);
-static void acpi_ac_notify(struct acpi_device *device, u32 event);
+static void acpi_ac_notify(acpi_handle handle, u32 event, void *data);
 
 static const struct acpi_device_id ac_device_ids[] = {
        {"ACPI0003", 0},
@@ -54,11 +54,9 @@ static struct acpi_driver acpi_ac_driver = {
        .name = "ac",
        .class = ACPI_AC_CLASS,
        .ids = ac_device_ids,
-       .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
        .ops = {
                .add = acpi_ac_add,
                .remove = acpi_ac_remove,
-               .notify = acpi_ac_notify,
                },
        .drv.pm = &acpi_ac_pm,
 };
@@ -128,8 +126,9 @@ static enum power_supply_property ac_props[] = {
 };
 
 /* Driver Model */
-static void acpi_ac_notify(struct acpi_device *device, u32 event)
+static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
 {
+       struct acpi_device *device = data;
        struct acpi_ac *ac = acpi_driver_data(device);
 
        if (!ac)
@@ -235,7 +234,7 @@ static int acpi_ac_add(struct acpi_device *device)
 
        result = acpi_ac_get_state(ac);
        if (result)
-               goto end;
+               goto err_release_ac;
 
        psy_cfg.drv_data = ac;
 
@@ -248,7 +247,7 @@ static int acpi_ac_add(struct acpi_device *device)
                                            &ac->charger_desc, &psy_cfg);
        if (IS_ERR(ac->charger)) {
                result = PTR_ERR(ac->charger);
-               goto end;
+               goto err_release_ac;
        }
 
        pr_info("%s [%s] (%s)\n", acpi_device_name(device),
@@ -256,9 +255,19 @@ static int acpi_ac_add(struct acpi_device *device)
 
        ac->battery_nb.notifier_call = acpi_ac_battery_notify;
        register_acpi_notifier(&ac->battery_nb);
-end:
+
+       result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY,
+                                                acpi_ac_notify);
        if (result)
-               kfree(ac);
+               goto err_unregister;
+
+       return 0;
+
+err_unregister:
+       power_supply_unregister(ac->charger);
+       unregister_acpi_notifier(&ac->battery_nb);
+err_release_ac:
+       kfree(ac);
 
        return result;
 }
@@ -297,6 +306,8 @@ static void acpi_ac_remove(struct acpi_device *device)
 
        ac = acpi_driver_data(device);
 
+       acpi_dev_remove_notify_handler(device, ACPI_ALL_NOTIFY,
+                                      acpi_ac_notify);
        power_supply_unregister(ac->charger);
        unregister_acpi_notifier(&ac->battery_nb);
 
index 4cf4aef7ce0c17f68f2e1bda5363e0c634ca9bff..9b55d1593d160c86430dddcced2ddb4b2248955b 100644 (file)
@@ -51,12 +51,11 @@ acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address,
        return AE_OK;
 }
 
-static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev,
-               const struct acpi_device_id *id)
+int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
 {
        acpi_status status;
 
-       status = acpi_install_address_space_handler(adev->handle,
+       status = acpi_install_address_space_handler(handle,
                        ACPI_ADR_SPACE_CMOS,
                        &acpi_cmos_rtc_space_handler,
                        NULL, NULL);
@@ -67,18 +66,30 @@ static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev,
 
        return 1;
 }
+EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler);
 
-static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev)
+void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
 {
-       if (ACPI_FAILURE(acpi_remove_address_space_handler(adev->handle,
+       if (ACPI_FAILURE(acpi_remove_address_space_handler(handle,
                        ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler)))
                pr_err("Error removing CMOS-RTC region handler\n");
 }
+EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler);
+
+static int acpi_cmos_rtc_attach_handler(struct acpi_device *adev, const struct acpi_device_id *id)
+{
+       return acpi_install_cmos_rtc_space_handler(adev->handle);
+}
+
+static void acpi_cmos_rtc_detach_handler(struct acpi_device *adev)
+{
+       acpi_remove_cmos_rtc_space_handler(adev->handle);
+}
 
 static struct acpi_scan_handler cmos_rtc_handler = {
        .ids = acpi_cmos_rtc_ids,
-       .attach = acpi_install_cmos_rtc_space_handler,
-       .detach = acpi_remove_cmos_rtc_space_handler,
+       .attach = acpi_cmos_rtc_attach_handler,
+       .detach = acpi_cmos_rtc_detach_handler,
 };
 
 void __init acpi_cmos_rtc_init(void)
index e648158368a7d8802f129e6da1509fa054f8af71..e120a96e1eaee803c5beb0741072471de98a7bcf 100644 (file)
@@ -172,7 +172,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
                        fru_text = "";
                sec_type = (guid_t *)gdata->section_type;
                if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
-                       struct cper_sec_mem_err *mem = (void *)(gdata + 1);
+                       struct cper_sec_mem_err *mem = acpi_hest_get_payload(gdata);
 
                        if (gdata->error_data_length >= sizeof(*mem))
                                trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
index f9aa02cac6d11b6c4d7b4fb18fc74e79188f3a88..c711db8a9c332843bc84482051d4d89ef977cd00 100644 (file)
@@ -9,9 +9,11 @@
  * Copyright (C) 2013, Intel Corporation
  *                     Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  */
+#define pr_fmt(fmt) "ACPI: " fmt
 
 #include <linux/acpi.h>
 #include <linux/device.h>
+#include <linux/dmi.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -21,6 +23,8 @@
 
 #include <asm/cpu.h>
 
+#include <xen/xen.h>
+
 #include "internal.h"
 
 DEFINE_PER_CPU(struct acpi_processor *, processors);
@@ -508,54 +512,110 @@ static void acpi_processor_remove(struct acpi_device *device)
 }
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
-#ifdef CONFIG_X86
-static bool acpi_hwp_native_thermal_lvt_set;
-static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle,
-                                                         u32 lvl,
-                                                         void *context,
-                                                         void **rv)
+#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
+bool __init processor_physically_present(acpi_handle handle)
+{
+       int cpuid, type;
+       u32 acpi_id;
+       acpi_status status;
+       acpi_object_type acpi_type;
+       unsigned long long tmp;
+       union acpi_object object = {};
+       struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+
+       status = acpi_get_type(handle, &acpi_type);
+       if (ACPI_FAILURE(status))
+               return false;
+
+       switch (acpi_type) {
+       case ACPI_TYPE_PROCESSOR:
+               status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
+               if (ACPI_FAILURE(status))
+                       return false;
+               acpi_id = object.processor.proc_id;
+               break;
+       case ACPI_TYPE_DEVICE:
+               status = acpi_evaluate_integer(handle, METHOD_NAME__UID,
+                                              NULL, &tmp);
+               if (ACPI_FAILURE(status))
+                       return false;
+               acpi_id = tmp;
+               break;
+       default:
+               return false;
+       }
+
+       if (xen_initial_domain())
+               /*
+                * When running as a Xen dom0 the number of processors Linux
+                * sees can be different from the real number of processors on
+                * the system, and we still need to execute _PDC or _OSC for
+                * all of them.
+                */
+               return xen_processor_present(acpi_id);
+
+       type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
+       cpuid = acpi_get_cpuid(handle, type, acpi_id);
+
+       return !invalid_logical_cpuid(cpuid);
+}
+
+/* vendor specific UUID indicating an Intel platform */
+static u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953";
+
+static acpi_status __init acpi_processor_osc(acpi_handle handle, u32 lvl,
+                                            void *context, void **rv)
 {
-       u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953";
-       u32 capbuf[2];
+       u32 capbuf[2] = {};
        struct acpi_osc_context osc_context = {
                .uuid_str = sb_uuid_str,
                .rev = 1,
                .cap.length = 8,
                .cap.pointer = capbuf,
        };
+       acpi_status status;
 
-       if (acpi_hwp_native_thermal_lvt_set)
-               return AE_CTRL_TERMINATE;
+       if (!processor_physically_present(handle))
+               return AE_OK;
 
-       capbuf[0] = 0x0000;
-       capbuf[1] = 0x1000; /* set bit 12 */
+       arch_acpi_set_proc_cap_bits(&capbuf[OSC_SUPPORT_DWORD]);
 
-       if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) {
-               if (osc_context.ret.pointer && osc_context.ret.length > 1) {
-                       u32 *capbuf_ret = osc_context.ret.pointer;
+       status = acpi_run_osc(handle, &osc_context);
+       if (ACPI_FAILURE(status))
+               return status;
 
-                       if (capbuf_ret[1] & 0x1000) {
-                               acpi_handle_info(handle,
-                                       "_OSC native thermal LVT Acked\n");
-                               acpi_hwp_native_thermal_lvt_set = true;
-                       }
-               }
-               kfree(osc_context.ret.pointer);
-       }
+       kfree(osc_context.ret.pointer);
 
        return AE_OK;
 }
 
-void __init acpi_early_processor_osc(void)
+static bool __init acpi_early_processor_osc(void)
 {
-       if (boot_cpu_has(X86_FEATURE_HWP)) {
-               acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
-                                   ACPI_UINT32_MAX,
-                                   acpi_hwp_native_thermal_lvt_osc,
-                                   NULL, NULL, NULL);
-               acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID,
-                                acpi_hwp_native_thermal_lvt_osc,
-                                NULL, NULL);
+       acpi_status status;
+
+       acpi_proc_quirk_mwait_check();
+
+       status = acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+                                    ACPI_UINT32_MAX, acpi_processor_osc, NULL,
+                                    NULL, NULL);
+       if (ACPI_FAILURE(status))
+               return false;
+
+       status = acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, acpi_processor_osc,
+                                 NULL, NULL);
+       if (ACPI_FAILURE(status))
+               return false;
+
+       return true;
+}
+
+void __init acpi_early_processor_control_setup(void)
+{
+       if (acpi_early_processor_osc()) {
+               pr_info("_OSC evaluated successfully for all CPUs\n");
+       } else {
+               pr_info("_OSC evaluation for CPUs failed, trying _PDC\n");
+               acpi_early_processor_set_pdc();
        }
 }
 #endif
index e9b8e8305e23e6086a84096ff6b09d24d97a88b8..33c3b16af556b5db693cb4cf8b9572c4ab26a65f 100644 (file)
@@ -557,6 +557,7 @@ static int acpi_tad_disable_timer(struct device *dev, u32 timer_id)
 static int acpi_tad_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
+       acpi_handle handle = ACPI_HANDLE(dev);
        struct acpi_tad_driver_data *dd = dev_get_drvdata(dev);
 
        device_init_wakeup(dev, false);
@@ -577,6 +578,7 @@ static int acpi_tad_remove(struct platform_device *pdev)
 
        pm_runtime_put_sync(dev);
        pm_runtime_disable(dev);
+       acpi_remove_cmos_rtc_space_handler(handle);
        return 0;
 }
 
@@ -589,6 +591,11 @@ static int acpi_tad_probe(struct platform_device *pdev)
        unsigned long long caps;
        int ret;
 
+       ret = acpi_install_cmos_rtc_space_handler(handle);
+       if (ret < 0) {
+               dev_info(dev, "Unable to install space handler\n");
+               return -ENODEV;
+       }
        /*
         * Initialization failure messages are mostly about firmware issues, so
         * print them at the "info" level.
@@ -596,22 +603,27 @@ static int acpi_tad_probe(struct platform_device *pdev)
        status = acpi_evaluate_integer(handle, "_GCP", NULL, &caps);
        if (ACPI_FAILURE(status)) {
                dev_info(dev, "Unable to get capabilities\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto remove_handler;
        }
 
        if (!(caps & ACPI_TAD_AC_WAKE)) {
                dev_info(dev, "Unsupported capabilities\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto remove_handler;
        }
 
        if (!acpi_has_method(handle, "_PRW")) {
                dev_info(dev, "Missing _PRW\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto remove_handler;
        }
 
        dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL);
-       if (!dd)
-               return -ENOMEM;
+       if (!dd) {
+               ret = -ENOMEM;
+               goto remove_handler;
+       }
 
        dd->capabilities = caps;
        dev_set_drvdata(dev, dd);
@@ -653,6 +665,11 @@ static int acpi_tad_probe(struct platform_device *pdev)
 
 fail:
        acpi_tad_remove(pdev);
+       /* Don't fallthrough because cmos rtc space handler is removed in acpi_tad_remove() */
+       return ret;
+
+remove_handler:
+       acpi_remove_cmos_rtc_space_handler(handle);
        return ret;
 }
 
index 62f4364e4460b4f5f7396e595a59d9f7e01e45dc..948e31f7ce6e70918c9034989cb7d6dbddf4a70b 100644 (file)
@@ -77,7 +77,7 @@ static DEFINE_MUTEX(video_list_lock);
 static LIST_HEAD(video_bus_head);
 static int acpi_video_bus_add(struct acpi_device *device);
 static void acpi_video_bus_remove(struct acpi_device *device);
-static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
+static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data);
 
 /*
  * Indices in the _BCL method response: the first two items are special,
@@ -104,7 +104,6 @@ static struct acpi_driver acpi_video_bus = {
        .ops = {
                .add = acpi_video_bus_add,
                .remove = acpi_video_bus_remove,
-               .notify = acpi_video_bus_notify,
                },
 };
 
@@ -1527,8 +1526,9 @@ static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
                                  acpi_osi_is_win8() ? 0 : 1);
 }
 
-static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
+static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
 {
+       struct acpi_device *device = data;
        struct acpi_video_bus *video = acpi_driver_data(device);
        struct input_dev *input;
        int keycode = 0;
@@ -2027,6 +2027,12 @@ static int acpi_video_bus_add(struct acpi_device *device)
        if (error)
                goto err_put_video;
 
+       /*
+        * HP ZBook Fury 16 G10 requires ACPI video's child devices have _PS0
+        * evaluated to have functional panel brightness control.
+        */
+       acpi_device_fix_up_power_extended(device);
+
        pr_info("%s [%s] (multi-head: %s  rom: %s  post: %s)\n",
               ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
               video->flags.multihead ? "yes" : "no",
@@ -2053,8 +2059,19 @@ static int acpi_video_bus_add(struct acpi_device *device)
 
        acpi_video_bus_add_notify_handler(video);
 
+       error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+                                               acpi_video_bus_notify);
+       if (error)
+               goto err_remove;
+
        return 0;
 
+err_remove:
+       mutex_lock(&video_list_lock);
+       list_del(&video->entry);
+       mutex_unlock(&video_list_lock);
+       acpi_video_bus_remove_notify_handler(video);
+       acpi_video_bus_unregister_backlight(video);
 err_put_video:
        acpi_video_bus_put_devices(video);
        kfree(video->attached_array);
@@ -2075,6 +2092,9 @@ static void acpi_video_bus_remove(struct acpi_device *device)
 
        video = acpi_driver_data(device);
 
+       acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
+                                      acpi_video_bus_notify);
+
        mutex_lock(&video_list_lock);
        list_del(&video->entry);
        mutex_unlock(&video_list_lock);
index 22f1f7a9e5a38110d788b49be52421f1610f7423..911875c5a5f190584e04a95cb81ef1c45e8b8595 100644 (file)
@@ -287,4 +287,6 @@ struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name);
 
 void acpi_db_uint32_to_hex_string(u32 value, char *buffer);
 
+void acpi_db_generate_interrupt(char *gsiv_arg);
+
 #endif                         /* __ACDEBUG_H__ */
index 778241173ed42406247a07a5e98bc84bd15960b9..f4c90fc99be2fbd8eb3d626e6c253e3b9b22adc4 100644 (file)
@@ -129,6 +129,7 @@ ACPI_GLOBAL(acpi_table_handler, acpi_gbl_table_handler);
 ACPI_GLOBAL(void *, acpi_gbl_table_handler_context);
 ACPI_GLOBAL(acpi_interface_handler, acpi_gbl_interface_handler);
 ACPI_GLOBAL(struct acpi_sci_handler_info *, acpi_gbl_sci_handler_list);
+ACPI_GLOBAL(struct acpi_ged_handler_info *, acpi_gbl_ged_handler_list);
 
 /* Owner ID support */
 
index 12d4a024f029ab980c99fe269d6281f25f943323..82563b44af35147dc85cf551a4655d45801bc06c 100644 (file)
@@ -543,6 +543,14 @@ struct acpi_field_info {
        u32 pkg_length;
 };
 
+/* Information about the interrupt ID and _EVT of a GED device */
+
+struct acpi_ged_handler_info {
+       struct acpi_ged_handler_info *next;
+       u32 int_id;             /* The interrupt ID that triggers the execution ofthe evt_method. */
+       struct acpi_namespace_node *evt_method; /* The _EVT method to be executed when an interrupt with ID = int_ID is received */
+};
+
 /*****************************************************************************
  *
  * Generic "state" object for stacks
@@ -560,25 +568,28 @@ struct acpi_field_info {
        u8                              descriptor_type; /* To differentiate various internal objs */\
        u8                              flags; \
        u16                             value; \
-       u16                             state;
+       u16                             state
 
        /* There are 2 bytes available here until the next natural alignment boundary */
 
 struct acpi_common_state {
-ACPI_STATE_COMMON};
+       ACPI_STATE_COMMON;
+};
 
 /*
  * Update state - used to traverse complex objects such as packages
  */
 struct acpi_update_state {
-       ACPI_STATE_COMMON union acpi_operand_object *object;
+       ACPI_STATE_COMMON;
+       union acpi_operand_object *object;
 };
 
 /*
  * Pkg state - used to traverse nested package structures
  */
 struct acpi_pkg_state {
-       ACPI_STATE_COMMON u32 index;
+       ACPI_STATE_COMMON;
+       u32 index;
        union acpi_operand_object *source_object;
        union acpi_operand_object *dest_object;
        struct acpi_walk_state *walk_state;
@@ -591,7 +602,8 @@ struct acpi_pkg_state {
  * Allows nesting of these constructs
  */
 struct acpi_control_state {
-       ACPI_STATE_COMMON u16 opcode;
+       ACPI_STATE_COMMON;
+       u16 opcode;
        union acpi_parse_object *predicate_op;
        u8 *aml_predicate_start;        /* Start of if/while predicate */
        u8 *package_end;        /* End of if/while block */
@@ -602,11 +614,13 @@ struct acpi_control_state {
  * Scope state - current scope during namespace lookups
  */
 struct acpi_scope_state {
-       ACPI_STATE_COMMON struct acpi_namespace_node *node;
+       ACPI_STATE_COMMON;
+       struct acpi_namespace_node *node;
 };
 
 struct acpi_pscope_state {
-       ACPI_STATE_COMMON u32 arg_count;        /* Number of fixed arguments */
+       ACPI_STATE_COMMON;
+       u32 arg_count;          /* Number of fixed arguments */
        union acpi_parse_object *op;    /* Current op being parsed */
        u8 *arg_end;            /* Current argument end */
        u8 *pkg_end;            /* Current package end */
@@ -618,7 +632,8 @@ struct acpi_pscope_state {
  * states are created when there are nested control methods executing.
  */
 struct acpi_thread_state {
-       ACPI_STATE_COMMON u8 current_sync_level;        /* Mutex Sync (nested acquire) level */
+       ACPI_STATE_COMMON;
+       u8 current_sync_level;  /* Mutex Sync (nested acquire) level */
        struct acpi_walk_state *walk_state_list;        /* Head of list of walk_states for this thread */
        union acpi_operand_object *acquired_mutex_list; /* List of all currently acquired mutexes */
        acpi_thread_id thread_id;       /* Running thread ID */
@@ -629,8 +644,8 @@ struct acpi_thread_state {
  * AML arguments
  */
 struct acpi_result_values {
-       ACPI_STATE_COMMON
-           union acpi_operand_object *obj_desc[ACPI_RESULTS_FRAME_OBJ_NUM];
+       ACPI_STATE_COMMON;
+       union acpi_operand_object *obj_desc[ACPI_RESULTS_FRAME_OBJ_NUM];
 };
 
 typedef
@@ -652,7 +667,8 @@ struct acpi_global_notify_handler {
  * handler/dispatcher.
  */
 struct acpi_notify_info {
-       ACPI_STATE_COMMON u8 handler_list_id;
+       ACPI_STATE_COMMON;
+       u8 handler_list_id;
        struct acpi_namespace_node *node;
        union acpi_operand_object *handler_list_head;
        struct acpi_global_notify_handler *global;
index e64aabe3d33a644d4cf81c720831bb51ec23f8ad..2e442f5a312322f30b4c96711396871f4b551cf6 100644 (file)
@@ -440,6 +440,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = {
        {{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER),
          METHOD_NO_RETURN_VALUE}},
 
+       {{"_DSC", METHOD_0ARGS,
+         METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},
+
        {{"_DSD", METHOD_0ARGS, /* ACPI 6.0 */
          METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */
        PACKAGE_INFO(ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1,
index 9eb68e0751c78300600115a27c699e6ffb43f384..3d99a9048585b7e326268113ef13b2c0a2a3d79d 100644 (file)
@@ -1010,6 +1010,64 @@ void acpi_db_display_resources(char *object_arg)
        acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_db_generate_ged
+ *
+ * PARAMETERS:  ged_arg             - Raw GED number, ascii string
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Simulate firing of a GED
+ *
+ ******************************************************************************/
+
+void acpi_db_generate_interrupt(char *gsiv_arg)
+{
+       u32 gsiv_number;
+       struct acpi_ged_handler_info *ged_info = acpi_gbl_ged_handler_list;
+
+       if (!ged_info) {
+               acpi_os_printf("No GED handling present\n");
+       }
+
+       gsiv_number = strtoul(gsiv_arg, NULL, 0);
+
+       while (ged_info) {
+
+               if (ged_info->int_id == gsiv_number) {
+                       struct acpi_object_list arg_list;
+                       union acpi_object arg0;
+                       acpi_handle evt_handle = ged_info->evt_method;
+                       acpi_status status;
+
+                       acpi_os_printf("Evaluate GED _EVT (GSIV=%d)\n",
+                                      gsiv_number);
+
+                       if (!evt_handle) {
+                               acpi_os_printf("Undefined _EVT method\n");
+                               return;
+                       }
+
+                       arg0.integer.type = ACPI_TYPE_INTEGER;
+                       arg0.integer.value = gsiv_number;
+
+                       arg_list.count = 1;
+                       arg_list.pointer = &arg0;
+
+                       status =
+                           acpi_evaluate_object(evt_handle, NULL, &arg_list,
+                                                NULL);
+                       if (ACPI_FAILURE(status)) {
+                               acpi_os_printf("Could not evaluate _EVT\n");
+                               return;
+                       }
+
+               }
+               ged_info = ged_info->next;
+       }
+}
+
 #if (!ACPI_REDUCED_HARDWARE)
 /*******************************************************************************
  *
index b8a48923064f5334a1c1b26eea4a49e5ce366273..861b12c334ab7702c1db2b2236a2de653783a0bd 100644 (file)
@@ -106,6 +106,7 @@ enum acpi_ex_debugger_commands {
        CMD_THREADS,
 
        CMD_TEST,
+       CMD_INTERRUPT,
 #endif
 };
 
@@ -185,6 +186,7 @@ static const struct acpi_db_command_info acpi_gbl_db_commands[] = {
        {"THREADS", 3},
 
        {"TEST", 1},
+       {"INTERRUPT", 1},
 #endif
        {NULL, 0}
 };
@@ -318,6 +320,7 @@ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = {
        {1, "  Gpes", "Display info on all GPE devices\n"},
        {1, "  Sci", "Generate an SCI\n"},
        {1, "  Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"},
+       {1, "  Interrupt <GSIV>", "Simulate an interrupt\n"},
 #endif
        {0, NULL, NULL}
 };
@@ -1064,6 +1067,11 @@ acpi_db_command_dispatch(char *input_buffer,
                acpi_os_printf("Event command not implemented\n");
                break;
 
+       case CMD_INTERRUPT:
+
+               acpi_db_generate_interrupt(acpi_gbl_db_args[1]);
+               break;
+
        case CMD_GPE:
 
                acpi_db_generate_gpe(acpi_gbl_db_args[1], acpi_gbl_db_args[2]);
index d3841ded3a818680f41139f26806c06f9dfcb7fa..75338a13c8028a8adeed5295ee1098b62f7a4d9e 100644 (file)
@@ -146,8 +146,8 @@ acpi_ds_result_push(union acpi_operand_object *object,
 
        if (!object) {
                ACPI_ERROR((AE_INFO,
-                           "Null Object! Obj=%p State=%p Num=%u",
-                           object, walk_state, walk_state->result_count));
+                           "Null Object! State=%p Num=%u",
+                           walk_state, walk_state->result_count));
                return (AE_BAD_PARAMETER);
        }
 
index 5d99b1a76c83b19114c58e9529bf116ec69cce2e..5241f4c01c765585ac3a47642602fc3d9ae68ede 100644 (file)
@@ -343,8 +343,7 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
        /* Copy the input buffer data to the transfer buffer */
 
        buffer = buffer_desc->buffer.pointer;
-       data_length = (buffer_length < source_desc->buffer.length ?
-                      buffer_length : source_desc->buffer.length);
+       data_length = ACPI_MIN(buffer_length, source_desc->buffer.length);
        memcpy(buffer, source_desc->buffer.pointer, data_length);
 
        /* Lock entire transaction if requested */
index 09029fe545f1449661c3d131c0e2f1a4545dda13..39e31030e5f49ad8ca589730fea72a8f6e228da8 100644 (file)
@@ -603,7 +603,7 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 
 /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
                         AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
-                        AML_FLAGS_EXEC_0A_0T_1R),
+                        AML_FLAGS_EXEC_0A_0T_1R | AML_NO_OPERAND_RESOLVE),
 
 /* ACPI 5.0 opcodes */
 
index 1bbba8585fa6fa83fc014799550ee5d8b3b775e8..c5f6c85a3a092bf0db1a2e233bc703a802f31f82 100644 (file)
@@ -37,7 +37,12 @@ void acpi_ut_init_stack_ptr_trace(void)
 {
        acpi_size current_sp;
 
+#pragma GCC diagnostic push
+#if defined(__GNUC__) && __GNUC__ >= 12
+#pragma GCC diagnostic ignored "-Wdangling-pointer="
+#endif
        acpi_gbl_entry_stack_pointer = &current_sp;
+#pragma GCC diagnostic pop
 }
 
 /*******************************************************************************
index 9c67ed02d797347cb3bf500e415e9d7c7258f362..969bf81e8d546a76ad9be2151db8b5ffab4ae137 100644 (file)
@@ -1034,8 +1034,9 @@ static void acpi_battery_refresh(struct acpi_battery *battery)
 }
 
 /* Driver Interface */
-static void acpi_battery_notify(struct acpi_device *device, u32 event)
+static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
 {
+       struct acpi_device *device = data;
        struct acpi_battery *battery = acpi_driver_data(device);
        struct power_supply *old;
 
@@ -1212,13 +1213,22 @@ static int acpi_battery_add(struct acpi_device *device)
 
        device_init_wakeup(&device->dev, 1);
 
-       return result;
+       result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY,
+                                                acpi_battery_notify);
+       if (result)
+               goto fail_pm;
+
+       return 0;
 
+fail_pm:
+       device_init_wakeup(&device->dev, 0);
+       unregister_pm_notifier(&battery->pm_nb);
 fail:
        sysfs_remove_battery(battery);
        mutex_destroy(&battery->lock);
        mutex_destroy(&battery->sysfs_lock);
        kfree(battery);
+
        return result;
 }
 
@@ -1228,10 +1238,16 @@ static void acpi_battery_remove(struct acpi_device *device)
 
        if (!device || !acpi_driver_data(device))
                return;
-       device_init_wakeup(&device->dev, 0);
+
        battery = acpi_driver_data(device);
+
+       acpi_dev_remove_notify_handler(device, ACPI_ALL_NOTIFY,
+                                      acpi_battery_notify);
+
+       device_init_wakeup(&device->dev, 0);
        unregister_pm_notifier(&battery->pm_nb);
        sysfs_remove_battery(battery);
+
        mutex_destroy(&battery->lock);
        mutex_destroy(&battery->sysfs_lock);
        kfree(battery);
@@ -1264,11 +1280,9 @@ static struct acpi_driver acpi_battery_driver = {
        .name = "battery",
        .class = ACPI_BATTERY_CLASS,
        .ids = battery_device_ids,
-       .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
        .ops = {
                .add = acpi_battery_add,
                .remove = acpi_battery_remove,
-               .notify = acpi_battery_notify,
                },
        .drv.pm = &acpi_battery_pm,
 };
index 2fc2b43a4ed3877e8a41a6f62d21b55340317723..f41dda2d34933661ea2908e4b94b1663058d583a 100644 (file)
@@ -554,6 +554,30 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device,
        acpi_os_wait_events_complete();
 }
 
+int acpi_dev_install_notify_handler(struct acpi_device *adev,
+                                   u32 handler_type,
+                                   acpi_notify_handler handler)
+{
+       acpi_status status;
+
+       status = acpi_install_notify_handler(adev->handle, handler_type,
+                                            handler, adev);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_install_notify_handler);
+
+void acpi_dev_remove_notify_handler(struct acpi_device *adev,
+                                   u32 handler_type,
+                                   acpi_notify_handler handler)
+{
+       acpi_remove_notify_handler(adev->handle, handler_type, handler);
+       acpi_os_wait_events_complete();
+}
+EXPORT_SYMBOL_GPL(acpi_dev_remove_notify_handler);
+
 /* Handle events targeting \_SB device (at present only graceful shutdown) */
 
 #define ACPI_SB_NOTIFY_SHUTDOWN_REQUEST 0x81
@@ -1005,8 +1029,10 @@ static int acpi_device_probe(struct device *dev)
                return -ENOSYS;
 
        ret = acpi_drv->ops.add(acpi_dev);
-       if (ret)
+       if (ret) {
+               acpi_dev->driver_data = NULL;
                return ret;
+       }
 
        pr_debug("Driver [%s] successfully bound to device [%s]\n",
                 acpi_drv->name, acpi_dev->pnp.bus_id);
@@ -1296,9 +1322,6 @@ static int __init acpi_bus_init(void)
                goto error1;
        }
 
-       /* Set capability bits for _OSC under processor scope */
-       acpi_early_processor_osc();
-
        /*
         * _OSC method may exist in module level code,
         * so it must be run after ACPI_FULL_INITIALIZATION
@@ -1314,7 +1337,7 @@ static int __init acpi_bus_init(void)
 
        acpi_sysfs_init();
 
-       acpi_early_processor_set_pdc();
+       acpi_early_processor_control_setup();
 
        /*
         * Maybe EC region is required at bus_scan/acpi_get_devices. So it
index 78d44e3fe1295ce434872aa97db4ffe547440059..46c6f8c35b4368bd41405695c38d807b3827a11d 100644 (file)
@@ -42,22 +42,32 @@ EXPORT_SYMBOL_GPL(unregister_acpi_hed_notifier);
  * it is used by HEST Generic Hardware Error Source with notify type
  * SCI.
  */
-static void acpi_hed_notify(struct acpi_device *device, u32 event)
+static void acpi_hed_notify(acpi_handle handle, u32 event, void *data)
 {
        blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL);
 }
 
 static int acpi_hed_add(struct acpi_device *device)
 {
+       int err;
+
        /* Only one hardware error device */
        if (hed_handle)
                return -EINVAL;
        hed_handle = device->handle;
-       return 0;
+
+       err = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+                                             acpi_hed_notify);
+       if (err)
+               hed_handle = NULL;
+
+       return err;
 }
 
 static void acpi_hed_remove(struct acpi_device *device)
 {
+       acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
+                                      acpi_hed_notify);
        hed_handle = NULL;
 }
 
@@ -68,7 +78,6 @@ static struct acpi_driver acpi_hed_driver = {
        .ops = {
                .add = acpi_hed_add,
                .remove = acpi_hed_remove,
-               .notify = acpi_hed_notify,
        },
 };
 module_acpi_driver(acpi_hed_driver);
index 956aed5afded9b4e4ec3cfcb946b7d5890583631..866c7c4ed2331710736606664e19098b49a4098e 100644 (file)
@@ -146,15 +146,13 @@ int acpi_wakeup_device_init(void);
                                   Processor
    -------------------------------------------------------------------------- */
 #ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
+void acpi_early_processor_control_setup(void);
 void acpi_early_processor_set_pdc(void);
-#else
-static inline void acpi_early_processor_set_pdc(void) {}
-#endif
 
-#ifdef CONFIG_X86
-void acpi_early_processor_osc(void);
+void acpi_proc_quirk_mwait_check(void);
+bool processor_physically_present(acpi_handle handle);
 #else
-static inline void acpi_early_processor_osc(void) {}
+static inline void acpi_early_processor_control_setup(void) {}
 #endif
 
 /* --------------------------------------------------------------------------
index 07204d482968471ce0c8b9e0f2cd847bcb029efd..f0e6738ae3c94146a3878f833f0406f3fedf44a0 100644 (file)
@@ -3282,6 +3282,23 @@ static void acpi_nfit_put_table(void *table)
        acpi_put_table(table);
 }
 
+static void acpi_nfit_notify(acpi_handle handle, u32 event, void *data)
+{
+       struct acpi_device *adev = data;
+
+       device_lock(&adev->dev);
+       __acpi_nfit_notify(&adev->dev, handle, event);
+       device_unlock(&adev->dev);
+}
+
+static void acpi_nfit_remove_notify_handler(void *data)
+{
+       struct acpi_device *adev = data;
+
+       acpi_dev_remove_notify_handler(adev, ACPI_DEVICE_NOTIFY,
+                                      acpi_nfit_notify);
+}
+
 void acpi_nfit_shutdown(void *data)
 {
        struct acpi_nfit_desc *acpi_desc = data;
@@ -3368,12 +3385,18 @@ static int acpi_nfit_add(struct acpi_device *adev)
 
        if (rc)
                return rc;
-       return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc);
-}
 
-static void acpi_nfit_remove(struct acpi_device *adev)
-{
-       /* see acpi_nfit_unregister */
+       rc = devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc);
+       if (rc)
+               return rc;
+
+       rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY,
+                                            acpi_nfit_notify);
+       if (rc)
+               return rc;
+
+       return devm_add_action_or_reset(dev, acpi_nfit_remove_notify_handler,
+                                       adev);
 }
 
 static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle)
@@ -3446,13 +3469,6 @@ void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event)
 }
 EXPORT_SYMBOL_GPL(__acpi_nfit_notify);
 
-static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
-{
-       device_lock(&adev->dev);
-       __acpi_nfit_notify(&adev->dev, adev->handle, event);
-       device_unlock(&adev->dev);
-}
-
 static const struct acpi_device_id acpi_nfit_ids[] = {
        { "ACPI0012", 0 },
        { "", 0 },
@@ -3464,8 +3480,6 @@ static struct acpi_driver acpi_nfit_driver = {
        .ids = acpi_nfit_ids,
        .ops = {
                .add = acpi_nfit_add,
-               .remove = acpi_nfit_remove,
-               .notify = acpi_nfit_notify,
        },
 };
 
index d6606a9f2da664a4cf1b87183133d6f0591db7ee..7dd6dbaa98c34a171909452f8de1edfbcb0c70fc 100644 (file)
@@ -132,6 +132,30 @@ static int map_rintc_hartid(struct acpi_subtable_header *entry,
        return -EINVAL;
 }
 
+/*
+ * Retrieve LoongArch CPU physical id
+ */
+static int map_core_pic_id(struct acpi_subtable_header *entry,
+               int device_declaration, u32 acpi_id, phys_cpuid_t *phys_id)
+{
+       struct acpi_madt_core_pic *core_pic =
+               container_of(entry, struct acpi_madt_core_pic, header);
+
+       if (!(core_pic->flags & ACPI_MADT_ENABLED))
+               return -ENODEV;
+
+       /* device_declaration means Device object in DSDT, in LoongArch
+        * system, logical processor acpi_id is required in _UID property
+        * of DSDT table, so we should check device_declaration here
+        */
+       if (device_declaration && (core_pic->processor_id == acpi_id)) {
+               *phys_id = core_pic->core_id;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
 static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
                                   int type, u32 acpi_id)
 {
@@ -165,6 +189,9 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
                } else if (header->type == ACPI_MADT_TYPE_RINTC) {
                        if (!map_rintc_hartid(header, type, acpi_id, &phys_id))
                                break;
+               } else if (header->type == ACPI_MADT_TYPE_CORE_PIC) {
+                       if (!map_core_pic_id(header, type, acpi_id, &phys_id))
+                               break;
                }
                entry += header->length;
        }
@@ -216,6 +243,8 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
                map_x2apic_id(header, type, acpi_id, &phys_id);
        else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT)
                map_gicc_mpidr(header, type, acpi_id, &phys_id);
+       else if (header->type == ACPI_MADT_TYPE_CORE_PIC)
+               map_core_pic_id(header, type, acpi_id, &phys_id);
 
 exit:
        kfree(buffer.pointer);
index 18fb04523f93bd71ede3495ecd3bb3d34d2c17fa..1a8591e9a9bf1a215b058ee227e6b1ec8fe8c4d5 100644 (file)
@@ -9,71 +9,19 @@
 
 #define pr_fmt(fmt) "ACPI: " fmt
 
-#include <linux/dmi.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 
-#include <xen/xen.h>
-
 #include "internal.h"
 
-static bool __init processor_physically_present(acpi_handle handle)
-{
-       int cpuid, type;
-       u32 acpi_id;
-       acpi_status status;
-       acpi_object_type acpi_type;
-       unsigned long long tmp;
-       union acpi_object object = { 0 };
-       struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
-
-       status = acpi_get_type(handle, &acpi_type);
-       if (ACPI_FAILURE(status))
-               return false;
-
-       switch (acpi_type) {
-       case ACPI_TYPE_PROCESSOR:
-               status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
-               if (ACPI_FAILURE(status))
-                       return false;
-               acpi_id = object.processor.proc_id;
-               break;
-       case ACPI_TYPE_DEVICE:
-               status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
-               if (ACPI_FAILURE(status))
-                       return false;
-               acpi_id = tmp;
-               break;
-       default:
-               return false;
-       }
-
-       if (xen_initial_domain())
-               /*
-                * When running as a Xen dom0 the number of processors Linux
-                * sees can be different from the real number of processors on
-                * the system, and we still need to execute _PDC for all of
-                * them.
-                */
-               return xen_processor_present(acpi_id);
-
-       type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
-       cpuid = acpi_get_cpuid(handle, type, acpi_id);
-
-       return !invalid_logical_cpuid(cpuid);
-}
-
 static void acpi_set_pdc_bits(u32 *buf)
 {
        buf[0] = ACPI_PDC_REVISION_ID;
        buf[1] = 1;
 
-       /* Enable coordination with firmware's _TSD info */
-       buf[2] = ACPI_PDC_SMP_T_SWCOORD;
-
        /* Twiddle arch-specific bits needed for _PDC */
-       arch_acpi_set_pdc_bits(buf);
+       arch_acpi_set_proc_cap_bits(&buf[2]);
 }
 
 static struct acpi_object_list *acpi_processor_alloc_pdc(void)
@@ -123,20 +71,6 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
 {
        acpi_status status = AE_OK;
 
-       if (boot_option_idle_override == IDLE_NOMWAIT) {
-               /*
-                * If mwait is disabled for CPU C-states, the C2C3_FFH access
-                * mode will be disabled in the parameter of _PDC object.
-                * Of course C1_FFH access mode will also be disabled.
-                */
-               union acpi_object *obj;
-               u32 *buffer = NULL;
-
-               obj = pdc_in->pointer;
-               buffer = (u32 *)(obj->buffer.pointer);
-               buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
-
-       }
        status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
 
        if (ACPI_FAILURE(status))
@@ -174,36 +108,9 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
        return AE_OK;
 }
 
-static int __init set_no_mwait(const struct dmi_system_id *id)
-{
-       pr_notice("%s detected - disabling mwait for CPU C-states\n",
-                 id->ident);
-       boot_option_idle_override = IDLE_NOMWAIT;
-       return 0;
-}
-
-static const struct dmi_system_id processor_idle_dmi_table[] __initconst = {
-       {
-       set_no_mwait, "Extensa 5220", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-       DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
-       DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
-       {},
-};
-
-static void __init processor_dmi_check(void)
-{
-       /*
-        * Check whether the system is DMI table. If yes, OSPM
-        * should not use mwait for CPU-states.
-        */
-       dmi_check_system(processor_idle_dmi_table);
-}
-
 void __init acpi_early_processor_set_pdc(void)
 {
-       processor_dmi_check();
+       acpi_proc_quirk_mwait_check();
 
        acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
index 1dd8d5aebf678900e7d6abd6d8d03e1d18f4b1f7..32cfa3f4efd3d290637dd0efe918eaf7ccc3ab99 100644 (file)
@@ -470,6 +470,49 @@ static const struct dmi_system_id asus_laptop[] = {
        { }
 };
 
+static const struct dmi_system_id tongfang_gm_rg[] = {
+       {
+               .ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
+               },
+       },
+       { }
+};
+
+static const struct dmi_system_id maingear_laptop[] = {
+       {
+               .ident = "MAINGEAR Vector Pro 2 15",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"),
+               }
+       },
+       {
+               .ident = "MAINGEAR Vector Pro 2 17",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"),
+               },
+       },
+       { }
+};
+
+static const struct dmi_system_id pcspecialist_laptop[] = {
+       {
+               .ident = "PCSpecialist Elimina Pro 16 M",
+               /*
+                * Some models have product-name "Elimina Pro 16 M",
+                * others "GM6BGEQ". Match on board-name to match both.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"),
+                       DMI_MATCH(DMI_BOARD_NAME, "GM6BGEQ"),
+               },
+       },
+       { }
+};
+
 static const struct dmi_system_id lg_laptop[] = {
        {
                .ident = "LG Electronics 17U70P",
@@ -493,6 +536,9 @@ struct irq_override_cmp {
 static const struct irq_override_cmp override_table[] = {
        { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
        { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
+       { tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
+       { maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
+       { pcspecialist_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
        { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
 };
 
@@ -512,6 +558,28 @@ static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
                        return entry->override;
        }
 
+#ifdef CONFIG_X86
+       /*
+        * Always use the MADT override info, except for the i8042 PS/2 ctrl
+        * IRQs (1 and 12). For these the DSDT IRQ settings should sometimes
+        * be used otherwise PS/2 keyboards / mice will not work.
+        */
+       if (gsi != 1 && gsi != 12)
+               return true;
+
+       /* If the override comes from an INT_SRC_OVR MADT entry, honor it. */
+       if (acpi_int_src_ovr[gsi])
+               return true;
+
+       /*
+        * IRQ override isn't needed on modern AMD Zen systems and
+        * this override breaks active low IRQs on AMD Ryzen 6000 and
+        * newer systems. Skip it.
+        */
+       if (boot_cpu_has(X86_FEATURE_ZEN))
+               return false;
+#endif
+
        return true;
 }
 
index 902763430d5671fa8c50e69fdf472c97535198dd..531a9e3df7178e55960f606d78ec1a4a04a038ef 100644 (file)
@@ -795,6 +795,9 @@ static const char * const acpi_ignore_dep_ids[] = {
 /* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */
 static const char * const acpi_honor_dep_ids[] = {
        "INT3472", /* Camera sensor PMIC / clk and regulator info */
+       "INTC1059", /* IVSC (TGL) driver must be loaded to allow i2c access to camera sensors */
+       "INTC1095", /* IVSC (ADL) driver must be loaded to allow i2c access to camera sensors */
+       "INTC100A", /* IVSC (RPL) driver must be loaded to allow i2c access to camera sensors */
        NULL
 };
 
@@ -1714,6 +1717,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
                {"BSG1160", },
                {"BSG2150", },
                {"CSC3551", },
+               {"CSC3556", },
                {"INT33FE", },
                {"INT3515", },
                /* Non-conforming _HID for Cirrus Logic already released */
index f9f6ebb08fdb76f58cf1f663d04e2d00b4e8a8ee..419590f41ed5f172c21b3510ad3c4e4a8bdd6323 100644 (file)
@@ -82,10 +82,6 @@ static int tzp;
 module_param(tzp, int, 0444);
 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
 
-static int nocrt;
-module_param(nocrt, int, 0);
-MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
-
 static int off;
 module_param(off, int, 0);
 MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
@@ -96,35 +92,27 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
 
 static struct workqueue_struct *acpi_thermal_pm_queue;
 
-struct acpi_thermal_critical {
-       unsigned long temperature;
-       bool valid;
-};
-
-struct acpi_thermal_hot {
+struct acpi_thermal_trip {
        unsigned long temperature;
        bool valid;
 };
 
 struct acpi_thermal_passive {
+       struct acpi_thermal_trip trip;
        struct acpi_handle_list devices;
-       unsigned long temperature;
        unsigned long tc1;
        unsigned long tc2;
        unsigned long tsp;
-       bool valid;
 };
 
 struct acpi_thermal_active {
+       struct acpi_thermal_trip trip;
        struct acpi_handle_list devices;
-       unsigned long temperature;
-       bool valid;
-       bool enabled;
 };
 
 struct acpi_thermal_trips {
-       struct acpi_thermal_critical critical;
-       struct acpi_thermal_hot hot;
+       struct acpi_thermal_trip critical;
+       struct acpi_thermal_trip hot;
        struct acpi_thermal_passive passive;
        struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
 };
@@ -137,6 +125,7 @@ struct acpi_thermal {
        unsigned long polling_frequency;
        volatile u8 zombie;
        struct acpi_thermal_trips trips;
+       struct thermal_trip *trip_table;
        struct acpi_handle_list devices;
        struct thermal_zone_device *thermal_zone;
        int kelvin_offset;      /* in millidegrees */
@@ -190,7 +179,16 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
        return 0;
 }
 
-static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
+static int acpi_thermal_temp(struct acpi_thermal *tz, int temp_deci_k)
+{
+       if (temp_deci_k == THERMAL_TEMP_INVALID)
+               return THERMAL_TEMP_INVALID;
+
+       return deci_kelvin_to_millicelsius_with_offset(temp_deci_k,
+                                                      tz->kelvin_offset);
+}
+
+static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
 {
        acpi_status status;
        unsigned long long tmp;
@@ -255,9 +253,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
        }
 
        /* Passive (optional) */
-       if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.valid) ||
+       if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.trip.valid) ||
            flag == ACPI_TRIPS_INIT) {
-               valid = tz->trips.passive.valid;
+               valid = tz->trips.passive.trip.valid;
                if (psv == -1) {
                        status = AE_SUPPORT;
                } else if (psv > 0) {
@@ -269,44 +267,44 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                }
 
                if (ACPI_FAILURE(status)) {
-                       tz->trips.passive.valid = false;
+                       tz->trips.passive.trip.valid = false;
                } else {
-                       tz->trips.passive.temperature = tmp;
-                       tz->trips.passive.valid = true;
+                       tz->trips.passive.trip.temperature = tmp;
+                       tz->trips.passive.trip.valid = true;
                        if (flag == ACPI_TRIPS_INIT) {
                                status = acpi_evaluate_integer(tz->device->handle,
                                                               "_TC1", NULL, &tmp);
                                if (ACPI_FAILURE(status))
-                                       tz->trips.passive.valid = false;
+                                       tz->trips.passive.trip.valid = false;
                                else
                                        tz->trips.passive.tc1 = tmp;
 
                                status = acpi_evaluate_integer(tz->device->handle,
                                                               "_TC2", NULL, &tmp);
                                if (ACPI_FAILURE(status))
-                                       tz->trips.passive.valid = false;
+                                       tz->trips.passive.trip.valid = false;
                                else
                                        tz->trips.passive.tc2 = tmp;
 
                                status = acpi_evaluate_integer(tz->device->handle,
                                                               "_TSP", NULL, &tmp);
                                if (ACPI_FAILURE(status))
-                                       tz->trips.passive.valid = false;
+                                       tz->trips.passive.trip.valid = false;
                                else
                                        tz->trips.passive.tsp = tmp;
                        }
                }
        }
-       if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.valid) {
+       if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.trip.valid) {
                memset(&devices, 0, sizeof(struct acpi_handle_list));
                status = acpi_evaluate_reference(tz->device->handle, "_PSL",
                                                 NULL, &devices);
                if (ACPI_FAILURE(status)) {
                        acpi_handle_info(tz->device->handle,
                                         "Invalid passive threshold\n");
-                       tz->trips.passive.valid = false;
+                       tz->trips.passive.trip.valid = false;
                } else {
-                       tz->trips.passive.valid = true;
+                       tz->trips.passive.trip.valid = true;
                }
 
                if (memcmp(&tz->trips.passive.devices, &devices,
@@ -317,24 +315,24 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                }
        }
        if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
-               if (valid != tz->trips.passive.valid)
+               if (valid != tz->trips.passive.trip.valid)
                        ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
        }
 
        /* Active (optional) */
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
                char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
-               valid = tz->trips.active[i].valid;
+               valid = tz->trips.active[i].trip.valid;
 
                if (act == -1)
                        break; /* disable all active trip points */
 
                if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) &&
-                   tz->trips.active[i].valid)) {
+                   tz->trips.active[i].trip.valid)) {
                        status = acpi_evaluate_integer(tz->device->handle,
                                                       name, NULL, &tmp);
                        if (ACPI_FAILURE(status)) {
-                               tz->trips.active[i].valid = false;
+                               tz->trips.active[i].trip.valid = false;
                                if (i == 0)
                                        break;
 
@@ -342,35 +340,36 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                                        break;
 
                                if (i == 1)
-                                       tz->trips.active[0].temperature = celsius_to_deci_kelvin(act);
+                                       tz->trips.active[0].trip.temperature =
+                                                       celsius_to_deci_kelvin(act);
                                else
                                        /*
                                         * Don't allow override higher than
                                         * the next higher trip point
                                         */
-                                       tz->trips.active[i-1].temperature =
+                                       tz->trips.active[i-1].trip.temperature =
                                                min_t(unsigned long,
-                                                     tz->trips.active[i-2].temperature,
+                                                     tz->trips.active[i-2].trip.temperature,
                                                      celsius_to_deci_kelvin(act));
 
                                break;
                        } else {
-                               tz->trips.active[i].temperature = tmp;
-                               tz->trips.active[i].valid = true;
+                               tz->trips.active[i].trip.temperature = tmp;
+                               tz->trips.active[i].trip.valid = true;
                        }
                }
 
                name[2] = 'L';
-               if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].valid) {
+               if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].trip.valid) {
                        memset(&devices, 0, sizeof(struct acpi_handle_list));
                        status = acpi_evaluate_reference(tz->device->handle,
                                                         name, NULL, &devices);
                        if (ACPI_FAILURE(status)) {
                                acpi_handle_info(tz->device->handle,
                                                 "Invalid active%d threshold\n", i);
-                               tz->trips.active[i].valid = false;
+                               tz->trips.active[i].trip.valid = false;
                        } else {
-                               tz->trips.active[i].valid = true;
+                               tz->trips.active[i].trip.valid = true;
                        }
 
                        if (memcmp(&tz->trips.active[i].devices, &devices,
@@ -381,10 +380,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                        }
                }
                if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
-                       if (valid != tz->trips.active[i].valid)
+                       if (valid != tz->trips.active[i].trip.valid)
                                ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
 
-               if (!tz->trips.active[i].valid)
+               if (!tz->trips.active[i].trip.valid)
                        break;
        }
 
@@ -398,24 +397,73 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                        ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
                }
        }
+}
+
+static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data)
+{
+       struct acpi_thermal_trip *acpi_trip = trip->priv;
+       struct acpi_thermal *tz = data;
+
+       if (!acpi_trip)
+               return 0;
+
+       if (acpi_trip->valid)
+               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
+       else
+               trip->temperature = THERMAL_TEMP_INVALID;
 
        return 0;
 }
 
+static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal,
+                                            unsigned long data)
+{
+       struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
+       int flag = data == ACPI_THERMAL_NOTIFY_THRESHOLDS ?
+                               ACPI_TRIPS_THRESHOLDS : ACPI_TRIPS_DEVICES;
+
+       __acpi_thermal_trips_update(tz, flag);
+
+       for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz);
+}
+
+static void acpi_queue_thermal_check(struct acpi_thermal *tz)
+{
+       if (!work_pending(&tz->thermal_check_work))
+               queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
+}
+
+static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event)
+{
+       struct acpi_device *adev = tz->device;
+
+       /*
+        * Use thermal_zone_device_exec() to carry out the trip points
+        * update, so as to protect thermal_get_trend() from getting stale
+        * trip point temperatures and to prevent thermal_zone_device_update()
+        * invoked from acpi_thermal_check_fn() from producing inconsistent
+        * results.
+        */
+       thermal_zone_device_exec(tz->thermal_zone,
+                                acpi_thermal_adjust_thermal_zone, event);
+       acpi_queue_thermal_check(tz);
+       acpi_bus_generate_netlink_event(adev->pnp.device_class,
+                                       dev_name(&adev->dev), event, 0);
+}
+
 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
 {
-       int i, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
        bool valid;
+       int i;
 
-       if (ret)
-               return ret;
+       __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
 
        valid = tz->trips.critical.valid |
                tz->trips.hot.valid |
-               tz->trips.passive.valid;
+               tz->trips.passive.trip.valid;
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
-               valid = valid || tz->trips.active[i].valid;
+               valid = valid || tz->trips.active[i].trip.valid;
 
        if (!valid) {
                pr_warn(FW_BUG "No valid trip found\n");
@@ -443,159 +491,55 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
        return 0;
 }
 
-static int thermal_get_trip_type(struct thermal_zone_device *thermal,
-                                int trip, enum thermal_trip_type *type)
+static int thermal_get_trend(struct thermal_zone_device *thermal,
+                            int trip_index, enum thermal_trend *trend)
 {
        struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
-       int i;
+       struct acpi_thermal_trip *acpi_trip;
+       int t, i;
 
-       if (!tz || trip < 0)
+       if (!tz || trip_index < 0)
                return -EINVAL;
 
-       if (tz->trips.critical.valid) {
-               if (!trip) {
-                       *type = THERMAL_TRIP_CRITICAL;
-                       return 0;
-               }
-               trip--;
-       }
-
-       if (tz->trips.hot.valid) {
-               if (!trip) {
-                       *type = THERMAL_TRIP_HOT;
-                       return 0;
-               }
-               trip--;
-       }
-
-       if (tz->trips.passive.valid) {
-               if (!trip) {
-                       *type = THERMAL_TRIP_PASSIVE;
-                       return 0;
-               }
-               trip--;
-       }
-
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].valid; i++) {
-               if (!trip) {
-                       *type = THERMAL_TRIP_ACTIVE;
-                       return 0;
-               }
-               trip--;
-       }
-
-       return -EINVAL;
-}
+       if (tz->trips.critical.valid)
+               trip_index--;
 
-static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
-                                int trip, int *temp)
-{
-       struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
-       int i;
+       if (tz->trips.hot.valid)
+               trip_index--;
 
-       if (!tz || trip < 0)
+       if (trip_index < 0)
                return -EINVAL;
 
-       if (tz->trips.critical.valid) {
-               if (!trip) {
-                       *temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.critical.temperature,
-                                       tz->kelvin_offset);
-                       return 0;
-               }
-               trip--;
-       }
-
-       if (tz->trips.hot.valid) {
-               if (!trip) {
-                       *temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.hot.temperature,
-                                       tz->kelvin_offset);
-                       return 0;
-               }
-               trip--;
-       }
-
-       if (tz->trips.passive.valid) {
-               if (!trip) {
-                       *temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.passive.temperature,
-                                       tz->kelvin_offset);
-                       return 0;
-               }
-               trip--;
-       }
-
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
-               tz->trips.active[i].valid; i++) {
-               if (!trip) {
-                       *temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.active[i].temperature,
-                                       tz->kelvin_offset);
-                       return 0;
-               }
-               trip--;
-       }
-
-       return -EINVAL;
-}
-
-static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
-                               int *temperature)
-{
-       struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
+       acpi_trip = &tz->trips.passive.trip;
+       if (acpi_trip->valid && !trip_index--) {
+               t = tz->trips.passive.tc1 * (tz->temperature -
+                                               tz->last_temperature) +
+                       tz->trips.passive.tc2 * (tz->temperature -
+                                               acpi_trip->temperature);
+               if (t > 0)
+                       *trend = THERMAL_TREND_RAISING;
+               else if (t < 0)
+                       *trend = THERMAL_TREND_DROPPING;
+               else
+                       *trend = THERMAL_TREND_STABLE;
 
-       if (tz->trips.critical.valid) {
-               *temperature = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.critical.temperature,
-                                       tz->kelvin_offset);
                return 0;
        }
 
-       return -EINVAL;
-}
-
-static int thermal_get_trend(struct thermal_zone_device *thermal,
-                            int trip, enum thermal_trend *trend)
-{
-       struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
-       enum thermal_trip_type type;
-       int i;
-
-       if (thermal_get_trip_type(thermal, trip, &type))
-               return -EINVAL;
-
-       if (type == THERMAL_TRIP_ACTIVE) {
-               int trip_temp;
-               int temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->temperature, tz->kelvin_offset);
-               if (thermal_get_trip_temp(thermal, trip, &trip_temp))
-                       return -EINVAL;
+       t = acpi_thermal_temp(tz, tz->temperature);
 
-               if (temp > trip_temp) {
-                       *trend = THERMAL_TREND_RAISING;
-                       return 0;
-               } else {
-                       /* Fall back on default trend */
-                       return -EINVAL;
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               acpi_trip = &tz->trips.active[i].trip;
+               if (acpi_trip->valid && !trip_index--) {
+                       if (t > acpi_thermal_temp(tz, acpi_trip->temperature)) {
+                               *trend = THERMAL_TREND_RAISING;
+                               return 0;
+                       }
+                       break;
                }
        }
 
-       /*
-        * tz->temperature has already been updated by generic thermal layer,
-        * before this callback being invoked
-        */
-       i = tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature) +
-           tz->trips.passive.tc2 * (tz->temperature - tz->trips.passive.temperature);
-
-       if (i > 0)
-               *trend = THERMAL_TREND_RAISING;
-       else if (i < 0)
-               *trend = THERMAL_TREND_DROPPING;
-       else
-               *trend = THERMAL_TREND_STABLE;
-
-       return 0;
+       return -EINVAL;
 }
 
 static void acpi_thermal_zone_device_hot(struct thermal_zone_device *thermal)
@@ -637,7 +581,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
        if (tz->trips.hot.valid)
                trip++;
 
-       if (tz->trips.passive.valid) {
+       if (tz->trips.passive.trip.valid) {
                trip++;
                for (i = 0; i < tz->trips.passive.devices.count; i++) {
                        handle = tz->trips.passive.devices.handles[i];
@@ -662,7 +606,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
        }
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-               if (!tz->trips.active[i].valid)
+               if (!tz->trips.active[i].trip.valid)
                        break;
 
                trip++;
@@ -709,9 +653,6 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
        .bind = acpi_thermal_bind_cooling_device,
        .unbind = acpi_thermal_unbind_cooling_device,
        .get_temp = thermal_get_temp,
-       .get_trip_type = thermal_get_trip_type,
-       .get_trip_temp = thermal_get_trip_temp,
-       .get_crit_temp = thermal_get_crit_temp,
        .get_trend = thermal_get_trend,
        .hot = acpi_thermal_zone_device_hot,
        .critical = acpi_thermal_zone_device_critical,
@@ -745,63 +686,97 @@ static void acpi_thermal_zone_sysfs_remove(struct acpi_thermal *tz)
 
 static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 {
-       int trips = 0;
+       struct acpi_thermal_trip *acpi_trip;
+       struct thermal_trip *trip;
+       int passive_delay = 0;
+       int trip_count = 0;
        int result;
-       acpi_status status;
        int i;
 
        if (tz->trips.critical.valid)
-               trips++;
+               trip_count++;
 
        if (tz->trips.hot.valid)
-               trips++;
+               trip_count++;
+
+       if (tz->trips.passive.trip.valid) {
+               trip_count++;
+               passive_delay = tz->trips.passive.tsp * 100;
+       }
 
-       if (tz->trips.passive.valid)
-               trips++;
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].trip.valid; i++)
+               trip_count++;
 
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].valid;
-            i++, trips++);
+       trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL);
+       if (!trip)
+               return -ENOMEM;
 
-       if (tz->trips.passive.valid)
-               tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz,
-                                                               &acpi_thermal_zone_ops, NULL,
-                                                               tz->trips.passive.tsp * 100,
-                                                               tz->polling_frequency * 100);
-       else
-               tz->thermal_zone =
-                       thermal_zone_device_register("acpitz", trips, 0, tz,
-                                                    &acpi_thermal_zone_ops, NULL,
-                                                    0, tz->polling_frequency * 100);
+       tz->trip_table = trip;
 
-       if (IS_ERR(tz->thermal_zone))
-               return -ENODEV;
+       if (tz->trips.critical.valid) {
+               trip->type = THERMAL_TRIP_CRITICAL;
+               trip->temperature = acpi_thermal_temp(tz, tz->trips.critical.temperature);
+               trip++;
+       }
+
+       if (tz->trips.hot.valid) {
+               trip->type = THERMAL_TRIP_HOT;
+               trip->temperature = acpi_thermal_temp(tz, tz->trips.hot.temperature);
+               trip++;
+       }
+
+       acpi_trip = &tz->trips.passive.trip;
+       if (acpi_trip->valid) {
+               trip->type = THERMAL_TRIP_PASSIVE;
+               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
+               trip->priv = acpi_trip;
+               trip++;
+       }
+
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               acpi_trip = &tz->trips.active[i].trip;
+
+               if (!acpi_trip->valid)
+                       break;
+
+               trip->type = THERMAL_TRIP_ACTIVE;
+               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
+               trip->priv = acpi_trip;
+               trip++;
+       }
+
+       tz->thermal_zone = thermal_zone_device_register_with_trips("acpitz",
+                                                                  tz->trip_table,
+                                                                  trip_count,
+                                                                  0, tz,
+                                                                  &acpi_thermal_zone_ops,
+                                                                  NULL,
+                                                                  passive_delay,
+                                                                  tz->polling_frequency * 100);
+       if (IS_ERR(tz->thermal_zone)) {
+               result = PTR_ERR(tz->thermal_zone);
+               goto free_trip_table;
+       }
 
        result = acpi_thermal_zone_sysfs_add(tz);
        if (result)
                goto unregister_tzd;
 
-       status =  acpi_bus_attach_private_data(tz->device->handle,
-                                              tz->thermal_zone);
-       if (ACPI_FAILURE(status)) {
-               result = -ENODEV;
-               goto remove_links;
-       }
-
        result = thermal_zone_device_enable(tz->thermal_zone);
        if (result)
-               goto acpi_bus_detach;
+               goto remove_links;
 
        dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
                 thermal_zone_device_id(tz->thermal_zone));
 
        return 0;
 
-acpi_bus_detach:
-       acpi_bus_detach_private_data(tz->device->handle);
 remove_links:
        acpi_thermal_zone_sysfs_remove(tz);
 unregister_tzd:
        thermal_zone_device_unregister(tz->thermal_zone);
+free_trip_table:
+       kfree(tz->trip_table);
 
        return result;
 }
@@ -810,8 +785,8 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
 {
        acpi_thermal_zone_sysfs_remove(tz);
        thermal_zone_device_unregister(tz->thermal_zone);
+       kfree(tz->trip_table);
        tz->thermal_zone = NULL;
-       acpi_bus_detach_private_data(tz->device->handle);
 }
 
 
@@ -819,14 +794,9 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
-static void acpi_queue_thermal_check(struct acpi_thermal *tz)
-{
-       if (!work_pending(&tz->thermal_check_work))
-               queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
-}
-
-static void acpi_thermal_notify(struct acpi_device *device, u32 event)
+static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
 {
+       struct acpi_device *device = data;
        struct acpi_thermal *tz = acpi_driver_data(device);
 
        if (!tz)
@@ -837,16 +807,8 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
                acpi_queue_thermal_check(tz);
                break;
        case ACPI_THERMAL_NOTIFY_THRESHOLDS:
-               acpi_thermal_trips_update(tz, ACPI_TRIPS_THRESHOLDS);
-               acpi_queue_thermal_check(tz);
-               acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                               dev_name(&device->dev), event, 0);
-               break;
        case ACPI_THERMAL_NOTIFY_DEVICES:
-               acpi_thermal_trips_update(tz, ACPI_TRIPS_DEVICES);
-               acpi_queue_thermal_check(tz);
-               acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                               dev_name(&device->dev), event, 0);
+               acpi_thermal_trips_update(tz, event);
                break;
        default:
                acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
@@ -997,11 +959,20 @@ static int acpi_thermal_add(struct acpi_device *device)
 
        pr_info("%s [%s] (%ld C)\n", acpi_device_name(device),
                acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature));
-       goto end;
 
+       result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+                                                acpi_thermal_notify);
+       if (result)
+               goto flush_wq;
+
+       return 0;
+
+flush_wq:
+       flush_workqueue(acpi_thermal_pm_queue);
+       acpi_thermal_unregister_thermal_zone(tz);
 free_memory:
        kfree(tz);
-end:
+
        return result;
 }
 
@@ -1012,10 +983,14 @@ static void acpi_thermal_remove(struct acpi_device *device)
        if (!device || !acpi_driver_data(device))
                return;
 
-       flush_workqueue(acpi_thermal_pm_queue);
        tz = acpi_driver_data(device);
 
+       acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
+                                      acpi_thermal_notify);
+
+       flush_workqueue(acpi_thermal_pm_queue);
        acpi_thermal_unregister_thermal_zone(tz);
+
        kfree(tz);
 }
 
@@ -1030,7 +1005,7 @@ static int acpi_thermal_suspend(struct device *dev)
 static int acpi_thermal_resume(struct device *dev)
 {
        struct acpi_thermal *tz;
-       int i, j, power_state, result;
+       int i, j, power_state;
 
        if (!dev)
                return -EINVAL;
@@ -1040,18 +1015,12 @@ static int acpi_thermal_resume(struct device *dev)
                return -EINVAL;
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-               if (!tz->trips.active[i].valid)
+               if (!tz->trips.active[i].trip.valid)
                        break;
 
-               tz->trips.active[i].enabled = true;
                for (j = 0; j < tz->trips.active[i].devices.count; j++) {
-                       result = acpi_bus_update_power(
-                                       tz->trips.active[i].devices.handles[j],
-                                       &power_state);
-                       if (result || (power_state != ACPI_STATE_D0)) {
-                               tz->trips.active[i].enabled = false;
-                               break;
-                       }
+                       acpi_bus_update_power(tz->trips.active[i].devices.handles[j],
+                                             &power_state);
                }
        }
 
@@ -1078,7 +1047,6 @@ static struct acpi_driver acpi_thermal_driver = {
        .ops = {
                .add = acpi_thermal_add,
                .remove = acpi_thermal_remove,
-               .notify = acpi_thermal_notify,
                },
        .drv.pm = &acpi_thermal_pm,
 };
@@ -1094,7 +1062,7 @@ static int thermal_act(const struct dmi_system_id *d) {
 static int thermal_nocrt(const struct dmi_system_id *d) {
        pr_notice("%s detected: disabling all critical thermal trip point actions.\n",
                  d->ident);
-       nocrt = 1;
+       crt = -1;
        return 0;
 }
 static int thermal_tzp(const struct dmi_system_id *d) {
index 18cc08c858cf20fa4b27b02175265aba1dd92aef..442396f6ed1f9c1ec3d6c920877788c014b88492 100644 (file)
@@ -445,6 +445,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_BOARD_NAME, "Lenovo IdeaPad S405"),
                },
        },
+       {
+        /* https://bugzilla.suse.com/show_bug.cgi?id=1208724 */
+        .callback = video_detect_force_native,
+        /* Lenovo Ideapad Z470 */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Z470"),
+               },
+       },
        {
         /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */
         .callback = video_detect_force_native,
@@ -486,6 +495,24 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "iMac11,3"),
                },
        },
+       {
+        /* https://gitlab.freedesktop.org/drm/amd/-/issues/1838 */
+        .callback = video_detect_force_native,
+        /* Apple iMac12,1 */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "iMac12,1"),
+               },
+       },
+       {
+        /* https://gitlab.freedesktop.org/drm/amd/-/issues/2753 */
+        .callback = video_detect_force_native,
+        /* Apple iMac12,2 */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "iMac12,2"),
+               },
+       },
        {
         /* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
         .callback = video_detect_force_native,
index c2b925f8cd4e41b06afa7f77529384a0e271e443..63d834dd381122eae4307751cbcd3a06abcaeb6e 100644 (file)
@@ -518,3 +518,38 @@ bool acpi_quirk_skip_acpi_ac_and_battery(void)
        return false;
 }
 EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery);
+
+/* This section provides a workaround for a specific x86 system
+ * which requires disabling of mwait to work correctly.
+ */
+static int __init acpi_proc_quirk_set_no_mwait(const struct dmi_system_id *id)
+{
+       pr_notice("%s detected - disabling mwait for CPU C-states\n",
+                 id->ident);
+       boot_option_idle_override = IDLE_NOMWAIT;
+       return 0;
+}
+
+static const struct dmi_system_id acpi_proc_quirk_mwait_dmi_table[] __initconst = {
+       {
+               .callback = acpi_proc_quirk_set_no_mwait,
+               .ident = "Extensa 5220",
+               .matches =  {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Columbia"),
+               },
+               .driver_data = NULL,
+       },
+       {}
+};
+
+void __init acpi_proc_quirk_mwait_check(void)
+{
+       /*
+        * Check whether the system is DMI table. If yes, OSPM
+        * should not use mwait for CPU-states.
+        */
+       dmi_check_system(acpi_proc_quirk_mwait_dmi_table);
+}
index 486c8271cab7ae71cf2be952935bc034e6ae3b20..d720f93d8b19c0fa62271d1e708998c352b5fb81 100644 (file)
@@ -6617,6 +6617,7 @@ err_init_binder_device_failed:
 
 err_alloc_device_names_failed:
        debugfs_remove_recursive(binder_debugfs_dir_entry_root);
+       binder_alloc_shrinker_exit();
 
        return ret;
 }
index 662a2a2e2e84a77b6fc9294d34c376f3e27712f2..e3db8297095a2fd58c8e3682a0b0d1c74e52e909 100644 (file)
@@ -1087,6 +1087,12 @@ int binder_alloc_shrinker_init(void)
        return ret;
 }
 
+void binder_alloc_shrinker_exit(void)
+{
+       unregister_shrinker(&binder_shrinker);
+       list_lru_destroy(&binder_alloc_lru);
+}
+
 /**
  * check_buffer() - verify that buffer/offset is safe to access
  * @alloc: binder_alloc for this proc
index 138d1d5af9ce36051893ee50a8e728d7bfbc2940..dc1e2b01dd64dbe7c7fd7decaadb8313c5b20904 100644 (file)
@@ -129,6 +129,7 @@ extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
                                                  int pid);
 extern void binder_alloc_init(struct binder_alloc *alloc);
 extern int binder_alloc_shrinker_init(void);
+extern void binder_alloc_shrinker_exit(void);
 extern void binder_alloc_vma_close(struct binder_alloc *alloc);
 extern struct binder_buffer *
 binder_alloc_prepare_to_free(struct binder_alloc *alloc,
index 370d18aca71e87653339e53002a7326812693665..c6ece32de8e31b69c71178ad89d02b9e90386940 100644 (file)
@@ -1100,7 +1100,14 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
                }
        } else {
                sdev->sector_size = ata_id_logical_sector_size(dev->id);
+               /*
+                * Stop the drive on suspend but do not issue START STOP UNIT
+                * on resume as this is not necessary and may fail: the device
+                * will be woken up by ata_port_pm_resume() with a port reset
+                * and device revalidation.
+                */
                sdev->manage_start_stop = 1;
+               sdev->no_start_on_resume = 1;
        }
 
        /*
index c1815b9dae68efc6810fce4560668f612d5a0db6..fe6690ecf5633409d89f9680e8361b4045209ab5 100644 (file)
@@ -509,73 +509,30 @@ static void __init cpu_dev_register_generic(void)
 }
 
 #ifdef CONFIG_GENERIC_CPU_VULNERABILITIES
-
-ssize_t __weak cpu_show_meltdown(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_spectre_v1(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_spectre_v2(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_spec_store_bypass(struct device *dev,
-                                         struct device_attribute *attr, char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_l1tf(struct device *dev,
-                            struct device_attribute *attr, char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_mds(struct device *dev,
-                           struct device_attribute *attr, char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_tsx_async_abort(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_itlb_multihit(struct device *dev,
-                                     struct device_attribute *attr, char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_srbds(struct device *dev,
+static ssize_t cpu_show_not_affected(struct device *dev,
                              struct device_attribute *attr, char *buf)
 {
        return sysfs_emit(buf, "Not affected\n");
 }
 
-ssize_t __weak cpu_show_mmio_stale_data(struct device *dev,
-                                       struct device_attribute *attr, char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_retbleed(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       return sysfs_emit(buf, "Not affected\n");
-}
+#define CPU_SHOW_VULN_FALLBACK(func)                                   \
+       ssize_t cpu_show_##func(struct device *,                        \
+                                 struct device_attribute *, char *)    \
+                __attribute__((weak, alias("cpu_show_not_affected")))
+
+CPU_SHOW_VULN_FALLBACK(meltdown);
+CPU_SHOW_VULN_FALLBACK(spectre_v1);
+CPU_SHOW_VULN_FALLBACK(spectre_v2);
+CPU_SHOW_VULN_FALLBACK(spec_store_bypass);
+CPU_SHOW_VULN_FALLBACK(l1tf);
+CPU_SHOW_VULN_FALLBACK(mds);
+CPU_SHOW_VULN_FALLBACK(tsx_async_abort);
+CPU_SHOW_VULN_FALLBACK(itlb_multihit);
+CPU_SHOW_VULN_FALLBACK(srbds);
+CPU_SHOW_VULN_FALLBACK(mmio_stale_data);
+CPU_SHOW_VULN_FALLBACK(retbleed);
+CPU_SHOW_VULN_FALLBACK(spec_rstack_overflow);
+CPU_SHOW_VULN_FALLBACK(gds);
 
 static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
 static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
@@ -588,6 +545,8 @@ static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
 static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
 static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL);
 static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
+static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL);
+static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
 
 static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_meltdown.attr,
@@ -601,6 +560,8 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_srbds.attr,
        &dev_attr_mmio_stale_data.attr,
        &dev_attr_retbleed.attr,
+       &dev_attr_spec_rstack_overflow.attr,
+       &dev_attr_gather_data_sampling.attr,
        NULL
 };
 
index 24afcc93ac0126215dde188510c4064652e3478b..2328cc05be36e99eb0f9083b0e138cf8bd52086a 100644 (file)
@@ -3675,7 +3675,7 @@ static int rbd_lock(struct rbd_device *rbd_dev)
        ret = ceph_cls_lock(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc,
                            RBD_LOCK_NAME, CEPH_CLS_LOCK_EXCLUSIVE, cookie,
                            RBD_LOCK_TAG, "", 0);
-       if (ret)
+       if (ret && ret != -EEXIST)
                return ret;
 
        __rbd_lock(rbd_dev, cookie);
@@ -3878,7 +3878,7 @@ static struct ceph_locker *get_lock_owner_info(struct rbd_device *rbd_dev)
                                 &rbd_dev->header_oloc, RBD_LOCK_NAME,
                                 &lock_type, &lock_tag, &lockers, &num_lockers);
        if (ret) {
-               rbd_warn(rbd_dev, "failed to retrieve lockers: %d", ret);
+               rbd_warn(rbd_dev, "failed to get header lockers: %d", ret);
                return ERR_PTR(ret);
        }
 
@@ -3940,8 +3940,10 @@ static int find_watcher(struct rbd_device *rbd_dev,
        ret = ceph_osdc_list_watchers(osdc, &rbd_dev->header_oid,
                                      &rbd_dev->header_oloc, &watchers,
                                      &num_watchers);
-       if (ret)
+       if (ret) {
+               rbd_warn(rbd_dev, "failed to get watchers: %d", ret);
                return ret;
+       }
 
        sscanf(locker->id.cookie, RBD_LOCK_COOKIE_PREFIX " %llu", &cookie);
        for (i = 0; i < num_watchers; i++) {
@@ -3985,8 +3987,12 @@ static int rbd_try_lock(struct rbd_device *rbd_dev)
                locker = refreshed_locker = NULL;
 
                ret = rbd_lock(rbd_dev);
-               if (ret != -EBUSY)
+               if (!ret)
+                       goto out;
+               if (ret != -EBUSY) {
+                       rbd_warn(rbd_dev, "failed to lock header: %d", ret);
                        goto out;
+               }
 
                /* determine if the current lock holder is still alive */
                locker = get_lock_owner_info(rbd_dev);
@@ -4089,11 +4095,8 @@ static int rbd_try_acquire_lock(struct rbd_device *rbd_dev)
 
        ret = rbd_try_lock(rbd_dev);
        if (ret < 0) {
-               rbd_warn(rbd_dev, "failed to lock header: %d", ret);
-               if (ret == -EBLOCKLISTED)
-                       goto out;
-
-               ret = 1; /* request lock anyway */
+               rbd_warn(rbd_dev, "failed to acquire lock: %d", ret);
+               goto out;
        }
        if (ret > 0) {
                up_write(&rbd_dev->lock_rwsem);
@@ -6627,12 +6630,11 @@ static int rbd_add_acquire_lock(struct rbd_device *rbd_dev)
                cancel_delayed_work_sync(&rbd_dev->lock_dwork);
                if (!ret)
                        ret = -ETIMEDOUT;
-       }
 
-       if (ret) {
-               rbd_warn(rbd_dev, "failed to acquire exclusive lock: %ld", ret);
-               return ret;
+               rbd_warn(rbd_dev, "failed to acquire lock: %ld", ret);
        }
+       if (ret)
+               return ret;
 
        /*
         * The lock may have been released by now, unless automatic lock
index c36d8b1ceeed74afc8311b218a7d516596c67814..39887556cf95907534f2627621bd774b79cd09d0 100644 (file)
@@ -25,7 +25,7 @@
 
 static struct device *rnbd_dev;
 static const struct class rnbd_dev_class = {
-       .name = "rnbd_client",
+       .name = "rnbd-client",
 };
 static struct kobject *rnbd_devs_kobj;
 
index 5676e6dd5b1672a8a0ff2798afa0a6cb4f5f8a59..06673c6ca255555dfa6c870f4c06dcb2cad6d8fc 100644 (file)
@@ -1870,15 +1870,16 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio)
 
 static void zram_bio_read(struct zram *zram, struct bio *bio)
 {
-       struct bvec_iter iter;
-       struct bio_vec bv;
-       unsigned long start_time;
+       unsigned long start_time = bio_start_io_acct(bio);
+       struct bvec_iter iter = bio->bi_iter;
 
-       start_time = bio_start_io_acct(bio);
-       bio_for_each_segment(bv, bio, iter) {
+       do {
                u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
                u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) <<
                                SECTOR_SHIFT;
+               struct bio_vec bv = bio_iter_iovec(bio, iter);
+
+               bv.bv_len = min_t(u32, bv.bv_len, PAGE_SIZE - offset);
 
                if (zram_bvec_read(zram, &bv, index, offset, bio) < 0) {
                        atomic64_inc(&zram->stats.failed_reads);
@@ -1890,22 +1891,26 @@ static void zram_bio_read(struct zram *zram, struct bio *bio)
                zram_slot_lock(zram, index);
                zram_accessed(zram, index);
                zram_slot_unlock(zram, index);
-       }
+
+               bio_advance_iter_single(bio, &iter, bv.bv_len);
+       } while (iter.bi_size);
+
        bio_end_io_acct(bio, start_time);
        bio_endio(bio);
 }
 
 static void zram_bio_write(struct zram *zram, struct bio *bio)
 {
-       struct bvec_iter iter;
-       struct bio_vec bv;
-       unsigned long start_time;
+       unsigned long start_time = bio_start_io_acct(bio);
+       struct bvec_iter iter = bio->bi_iter;
 
-       start_time = bio_start_io_acct(bio);
-       bio_for_each_segment(bv, bio, iter) {
+       do {
                u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
                u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) <<
                                SECTOR_SHIFT;
+               struct bio_vec bv = bio_iter_iovec(bio, iter);
+
+               bv.bv_len = min_t(u32, bv.bv_len, PAGE_SIZE - offset);
 
                if (zram_bvec_write(zram, &bv, index, offset, bio) < 0) {
                        atomic64_inc(&zram->stats.failed_writes);
@@ -1916,7 +1921,10 @@ static void zram_bio_write(struct zram *zram, struct bio *bio)
                zram_slot_lock(zram, index);
                zram_accessed(zram, index);
                zram_slot_unlock(zram, index);
-       }
+
+               bio_advance_iter_single(bio, &iter, bv.bv_len);
+       } while (iter.bi_size);
+
        bio_end_io_acct(bio, start_time);
        bio_endio(bio);
 }
index 21fe9854703f9e1b9593e700ce3f4bc756e7fbdb..4cb23b9e06ea4e4a034f5b8da59c31f4e79b0512 100644 (file)
@@ -2142,6 +2142,8 @@ static int sysc_reset(struct sysc *ddata)
                sysc_val = sysc_read_sysconfig(ddata);
                sysc_val |= sysc_mask;
                sysc_write(ddata, sysc_offset, sysc_val);
+               /* Flush posted write */
+               sysc_val = sysc_read_sysconfig(ddata);
        }
 
        if (ddata->cfg.srst_udelay)
index cf5499e51999bd4d6c6a6f39df939355a167bd74..ea6b4013bc38f48d3a4fe1996fb31e247d23ec5e 100644 (file)
@@ -510,70 +510,6 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip)
        return 0;
 }
 
-/*
- * Some AMD fTPM versions may cause stutter
- * https://www.amd.com/en/support/kb/faq/pa-410
- *
- * Fixes are available in two series of fTPM firmware:
- * 6.x.y.z series: 6.0.18.6 +
- * 3.x.y.z series: 3.57.y.5 +
- */
-#ifdef CONFIG_X86
-static bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
-{
-       u32 val1, val2;
-       u64 version;
-       int ret;
-
-       if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
-               return false;
-
-       ret = tpm_request_locality(chip);
-       if (ret)
-               return false;
-
-       ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val1, NULL);
-       if (ret)
-               goto release;
-       if (val1 != 0x414D4400U /* AMD */) {
-               ret = -ENODEV;
-               goto release;
-       }
-       ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_1, &val1, NULL);
-       if (ret)
-               goto release;
-       ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_2, &val2, NULL);
-
-release:
-       tpm_relinquish_locality(chip);
-
-       if (ret)
-               return false;
-
-       version = ((u64)val1 << 32) | val2;
-       if ((version >> 48) == 6) {
-               if (version >= 0x0006000000180006ULL)
-                       return false;
-       } else if ((version >> 48) == 3) {
-               if (version >= 0x0003005700000005ULL)
-                       return false;
-       } else {
-               return false;
-       }
-
-       dev_warn(&chip->dev,
-                "AMD fTPM version 0x%llx causes system stutter; hwrng disabled\n",
-                version);
-
-       return true;
-}
-#else
-static inline bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
-{
-       return false;
-}
-#endif /* CONFIG_X86 */
-
 static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 {
        struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
@@ -585,10 +521,20 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
        return tpm_get_random(chip, data, max);
 }
 
+static bool tpm_is_hwrng_enabled(struct tpm_chip *chip)
+{
+       if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM))
+               return false;
+       if (tpm_is_firmware_upgrade(chip))
+               return false;
+       if (chip->flags & TPM_CHIP_FLAG_HWRNG_DISABLED)
+               return false;
+       return true;
+}
+
 static int tpm_add_hwrng(struct tpm_chip *chip)
 {
-       if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip) ||
-           tpm_amd_is_rng_defective(chip))
+       if (!tpm_is_hwrng_enabled(chip))
                return 0;
 
        snprintf(chip->hwrng_name, sizeof(chip->hwrng_name),
@@ -693,7 +639,7 @@ int tpm_chip_register(struct tpm_chip *chip)
        return 0;
 
 out_hwrng:
-       if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip))
+       if (tpm_is_hwrng_enabled(chip))
                hwrng_unregister(&chip->hwrng);
 out_ppi:
        tpm_bios_log_teardown(chip);
@@ -718,8 +664,7 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
 void tpm_chip_unregister(struct tpm_chip *chip)
 {
        tpm_del_legacy_sysfs(chip);
-       if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip) &&
-           !tpm_amd_is_rng_defective(chip))
+       if (tpm_is_hwrng_enabled(chip))
                hwrng_unregister(&chip->hwrng);
        tpm_bios_log_teardown(chip);
        if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip))
index 1a5d09b1851345306c45e5a2cf71d603e00fbc86..9eb1a185901235f3c2fbddec4e9813d3bc254648 100644 (file)
@@ -463,6 +463,28 @@ static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
        return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
 }
 
+static int crb_check_flags(struct tpm_chip *chip)
+{
+       u32 val;
+       int ret;
+
+       ret = crb_request_locality(chip, 0);
+       if (ret)
+               return ret;
+
+       ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val, NULL);
+       if (ret)
+               goto release;
+
+       if (val == 0x414D4400U /* AMD */)
+               chip->flags |= TPM_CHIP_FLAG_HWRNG_DISABLED;
+
+release:
+       crb_relinquish_locality(chip, 0);
+
+       return ret;
+}
+
 static const struct tpm_class_ops tpm_crb = {
        .flags = TPM_OPS_AUTO_STARTUP,
        .status = crb_status,
@@ -800,6 +822,14 @@ static int crb_acpi_add(struct acpi_device *device)
        chip->acpi_dev_handle = device->handle;
        chip->flags = TPM_CHIP_FLAG_TPM2;
 
+       rc = tpm_chip_bootstrap(chip);
+       if (rc)
+               goto out;
+
+       rc = crb_check_flags(chip);
+       if (rc)
+               goto out;
+
        rc = tpm_chip_register(chip);
 
 out:
index cc42cf3de960fd7596fb7d10ef8d99b73fa718c2..7fa3d91042b265a858144e5c5f7fc540c741e587 100644 (file)
@@ -89,7 +89,7 @@ static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
        tpm_tis_flush(iobase);
 }
 
-static int interrupts = -1;
+static int interrupts;
 module_param(interrupts, int, 0444);
 MODULE_PARM_DESC(interrupts, "Enable interrupts");
 
@@ -162,12 +162,28 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L590"),
                },
        },
+       {
+               .callback = tpm_tis_disable_irq,
+               .ident = "ThinkStation P620",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P620"),
+               },
+       },
+       {
+               .callback = tpm_tis_disable_irq,
+               .ident = "TUXEDO InfinityBook S 15/17 Gen7",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TUXEDO InfinityBook S 15/17 Gen7"),
+               },
+       },
        {
                .callback = tpm_tis_disable_irq,
                .ident = "UPX-TGL",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "UPX-TGL"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "UPX-TGL01"),
                },
        },
        {}
index 93f38a8178bac24d664d1fc10bf4104f9b4b07a7..6b3b424addab4a5e3364169afef2855d91eb661e 100644 (file)
@@ -444,6 +444,7 @@ config COMMON_CLK_BD718XX
 config COMMON_CLK_FIXED_MMIO
        bool "Clock driver for Memory Mapped Fixed values"
        depends on COMMON_CLK && OF
+       depends on HAS_IOMEM
        help
          Support for Memory Mapped IO Fixed clocks
 
index b6c7c2725906c574a48fb43360806bdd3474d37c..44f435103c65a8eeb4a90121a0e12b81bbaa6623 100644 (file)
@@ -291,7 +291,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
        anatop_base = devm_of_iomap(dev, np, 0, NULL);
        of_node_put(np);
        if (WARN_ON(IS_ERR(anatop_base))) {
-               ret = PTR_ERR(base);
+               ret = PTR_ERR(anatop_base);
                goto unregister_hws;
        }
 
index 1ba421b38ec55efa9294f8378eba3435717d9ad9..e31f94387d87c0013b375eecbd3ed85414dc5d2d 100644 (file)
@@ -328,6 +328,14 @@ static const char * const atb_parents[] = {
        "syspll_d5"
 };
 
+static const char * const sspm_parents[] = {
+       "clk26m",
+       "univpll_d2_d4",
+       "syspll_d2_d2",
+       "univpll_d2_d2",
+       "syspll_d3"
+};
+
 static const char * const dpi0_parents[] = {
        "clk26m",
        "tvdpll_d2",
@@ -507,6 +515,9 @@ static const struct mtk_mux top_muxes[] = {
        /* CLK_CFG_6 */
        MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_ATB, "atb_sel",
                atb_parents, 0xa0, 0xa4, 0xa8, 0, 2, 7, 0x004, 24),
+       MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_SSPM, "sspm_sel",
+                                  sspm_parents, 0xa0, 0xa4, 0xa8, 8, 3, 15, 0x004, 25,
+                                  CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
        MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DPI0, "dpi0_sel",
                dpi0_parents, 0xa0, 0xa4, 0xa8, 16, 4, 23, 0x004, 26),
        MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SCAM, "scam_sel",
@@ -673,10 +684,18 @@ static const struct mtk_gate_regs infra3_cg_regs = {
        GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift,  \
                &mtk_clk_gate_ops_setclr)
 
+#define GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, _flag)  \
+       GATE_MTK_FLAGS(_id, _name, _parent, &infra2_cg_regs,    \
+                      _shift, &mtk_clk_gate_ops_setclr, _flag)
+
 #define GATE_INFRA3(_id, _name, _parent, _shift)               \
        GATE_MTK(_id, _name, _parent, &infra3_cg_regs, _shift,  \
                &mtk_clk_gate_ops_setclr)
 
+#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flag)  \
+       GATE_MTK_FLAGS(_id, _name, _parent, &infra3_cg_regs,    \
+                      _shift, &mtk_clk_gate_ops_setclr, _flag)
+
 static const struct mtk_gate infra_clks[] = {
        /* INFRA0 */
        GATE_INFRA0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "axi_sel", 0),
@@ -748,7 +767,11 @@ static const struct mtk_gate infra_clks[] = {
        GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick", "fufs_sel", 12),
        GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_BCLK, "infra_ufs_mp_sap_bck", "fufs_sel", 13),
        GATE_INFRA2(CLK_INFRA_MD32_BCLK, "infra_md32_bclk", "axi_sel", 14),
+       /* infra_sspm is main clock in co-processor, should not be closed in Linux. */
+       GATE_INFRA2_FLAGS(CLK_INFRA_SSPM, "infra_sspm", "sspm_sel", 15, CLK_IS_CRITICAL),
        GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, "infra_unipro_mbist", "axi_sel", 16),
+       /* infra_sspm_bus_hclk is main clock in co-processor, should not be closed in Linux. */
+       GATE_INFRA2_FLAGS(CLK_INFRA_SSPM_BUS_HCLK, "infra_sspm_bus_hclk", "axi_sel", 17, CLK_IS_CRITICAL),
        GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5", "i2c_sel", 18),
        GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter", "i2c_sel", 19),
        GATE_INFRA2(CLK_INFRA_I2C5_IMM, "infra_i2c5_imm", "i2c_sel", 20),
@@ -766,6 +789,10 @@ static const struct mtk_gate infra_clks[] = {
        GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self", "msdc50_0_sel", 0),
        GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self", "msdc50_0_sel", 1),
        GATE_INFRA3(CLK_INFRA_MSDC2_SELF, "infra_msdc2_self", "msdc50_0_sel", 2),
+       /* infra_sspm_26m_self is main clock in co-processor, should not be closed in Linux. */
+       GATE_INFRA3_FLAGS(CLK_INFRA_SSPM_26M_SELF, "infra_sspm_26m_self", "f_f26m_ck", 3, CLK_IS_CRITICAL),
+       /* infra_sspm_32k_self is main clock in co-processor, should not be closed in Linux. */
+       GATE_INFRA3_FLAGS(CLK_INFRA_SSPM_32K_SELF, "infra_sspm_32k_self", "f_f26m_ck", 4, CLK_IS_CRITICAL),
        GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", "axi_sel", 5),
        GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", "i2c_sel", 6),
        GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0", "msdc50_hclk_sel", 7),
index 8fef90bf962ff727138009fe65edbd703aefbc49..6fa7639a30503b679f58e182a5a0a27b97c47b28 100644 (file)
@@ -367,9 +367,9 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
         * 3. enable the lock detect module
         */
        if (MESON_PARM_APPLICABLE(&pll->current_en)) {
-               usleep_range(10, 20);
+               udelay(10);
                meson_parm_write(clk->map, &pll->current_en, 1);
-               usleep_range(40, 50);
+               udelay(40);
        }
 
        if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
index bca21df5116865b5fe8138c54f7003211c4ed8e2..62962ae84b77da1f3fd4f8b3f8bdf65bf328bc60 100644 (file)
@@ -3,13 +3,6 @@
 # Counter devices
 #
 
-menuconfig COUNTER
-       tristate "Counter support"
-       help
-         This enables counter device support through the Generic Counter
-         interface. You only need to enable this, if you also want to enable
-         one or more of the counter device drivers below.
-
 config I8254
        tristate
        select COUNTER
@@ -25,6 +18,13 @@ config I8254
 
          If built as a module its name will be i8254.
 
+menuconfig COUNTER
+       tristate "Counter support"
+       help
+         This enables counter device support through the Generic Counter
+         interface. You only need to enable this, if you also want to enable
+         one or more of the counter device drivers below.
+
 if COUNTER
 
 config 104_QUAD_8
index 81fba0dcbee9904afc610a0aa7bffe9ebba6760e..9a1e194d5cf8829a61ab6317c259fddd2e53b25a 100644 (file)
@@ -1012,8 +1012,8 @@ static int amd_pstate_update_status(const char *buf, size_t size)
        return 0;
 }
 
-static ssize_t show_status(struct kobject *kobj,
-                          struct kobj_attribute *attr, char *buf)
+static ssize_t status_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
 {
        ssize_t ret;
 
@@ -1024,7 +1024,7 @@ static ssize_t show_status(struct kobject *kobj,
        return ret;
 }
 
-static ssize_t store_status(struct kobject *a, struct kobj_attribute *b,
+static ssize_t status_store(struct device *a, struct device_attribute *b,
                            const char *buf, size_t count)
 {
        char *p = memchr(buf, '\n', count);
@@ -1043,7 +1043,7 @@ cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
 cpufreq_freq_attr_ro(amd_pstate_highest_perf);
 cpufreq_freq_attr_rw(energy_performance_preference);
 cpufreq_freq_attr_ro(energy_performance_available_preferences);
-define_one_global_rw(status);
+static DEVICE_ATTR_RW(status);
 
 static struct freq_attr *amd_pstate_attr[] = {
        &amd_pstate_max_freq,
@@ -1062,7 +1062,7 @@ static struct freq_attr *amd_pstate_epp_attr[] = {
 };
 
 static struct attribute *pstate_global_attributes[] = {
-       &status.attr,
+       &dev_attr_status.attr,
        NULL
 };
 
index c2d6d9c3c930dffaaa34dc245f14edeed1c9e7b7..b88af1262f1ab5fac89ffe557f496d148e3465f1 100644 (file)
@@ -120,20 +120,6 @@ static void psci_pd_remove(void)
        }
 }
 
-static bool psci_pd_try_set_osi_mode(void)
-{
-       int ret;
-
-       if (!psci_has_osi_support())
-               return false;
-
-       ret = psci_set_osi_mode(true);
-       if (ret)
-               return false;
-
-       return true;
-}
-
 static void psci_cpuidle_domain_sync_state(struct device *dev)
 {
        /*
@@ -152,15 +138,12 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct device_node *node;
-       bool use_osi;
+       bool use_osi = psci_has_osi_support();
        int ret = 0, pd_count = 0;
 
        if (!np)
                return -ENODEV;
 
-       /* If OSI mode is supported, let's try to enable it. */
-       use_osi = psci_pd_try_set_osi_mode();
-
        /*
         * Parse child nodes for the "#power-domain-cells" property and
         * initialize a genpd/genpd-of-provider pair when it's found.
@@ -170,33 +153,37 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
                        continue;
 
                ret = psci_pd_init(node, use_osi);
-               if (ret)
-                       goto put_node;
+               if (ret) {
+                       of_node_put(node);
+                       goto exit;
+               }
 
                pd_count++;
        }
 
        /* Bail out if not using the hierarchical CPU topology. */
        if (!pd_count)
-               goto no_pd;
+               return 0;
 
        /* Link genpd masters/subdomains to model the CPU topology. */
        ret = dt_idle_pd_init_topology(np);
        if (ret)
                goto remove_pd;
 
+       /* let's try to enable OSI. */
+       ret = psci_set_osi_mode(use_osi);
+       if (ret)
+               goto remove_pd;
+
        pr_info("Initialized CPU PM domain topology using %s mode\n",
                use_osi ? "OSI" : "PC");
        return 0;
 
-put_node:
-       of_node_put(node);
 remove_pd:
+       dt_idle_pd_remove_topology(np);
        psci_pd_remove();
+exit:
        pr_err("failed to create CPU PM domains ret=%d\n", ret);
-no_pd:
-       if (use_osi)
-               psci_set_osi_mode(false);
        return ret;
 }
 
index b37165514d4e71495e418967effdd0bb63856ba9..1af63c189039e9d40d3fd0863b37585feca271a9 100644 (file)
@@ -152,6 +152,30 @@ int dt_idle_pd_init_topology(struct device_node *np)
        return 0;
 }
 
+int dt_idle_pd_remove_topology(struct device_node *np)
+{
+       struct device_node *node;
+       struct of_phandle_args child, parent;
+       int ret;
+
+       for_each_child_of_node(np, node) {
+               if (of_parse_phandle_with_args(node, "power-domains",
+                                       "#power-domain-cells", 0, &parent))
+                       continue;
+
+               child.np = node;
+               child.args_count = 0;
+               ret = of_genpd_remove_subdomain(&parent, &child);
+               of_node_put(parent.np);
+               if (ret) {
+                       of_node_put(node);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 struct device *dt_idle_attach_cpu(int cpu, const char *name)
 {
        struct device *dev;
index a95483d08a02a8594b378c9022232e26f9237cb4..3be1f70f55b5c81b89ae69ac8d188e2ca743f2d6 100644 (file)
@@ -14,6 +14,8 @@ struct generic_pm_domain *dt_idle_pd_alloc(struct device_node *np,
 
 int dt_idle_pd_init_topology(struct device_node *np);
 
+int dt_idle_pd_remove_topology(struct device_node *np);
+
 struct device *dt_idle_attach_cpu(int cpu, const char *name);
 
 void dt_idle_detach_cpu(struct device *dev);
@@ -36,6 +38,11 @@ static inline int dt_idle_pd_init_topology(struct device_node *np)
        return 0;
 }
 
+static inline int dt_idle_pd_remove_topology(struct device_node *np)
+{
+       return 0;
+}
+
 static inline struct device *dt_idle_attach_cpu(int cpu, const char *name)
 {
        return NULL;
index ff9ddbbca3774a698a96c09080d7ed2aa6b4188f..68e73775392d98bc17255d09d4c1b0c725477fa9 100644 (file)
@@ -382,8 +382,8 @@ static void kick_trng(struct device *dev, int ent_delay)
                val = ent_delay;
                /* min. freq. count, equal to 1/4 of the entropy sample length */
                wr_reg32(&r4tst->rtfrqmin, val >> 2);
-               /* max. freq. count, equal to 16 times the entropy sample length */
-               wr_reg32(&r4tst->rtfrqmax, val << 4);
+               /* disable maximum frequency count */
+               wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE);
        }
 
        wr_reg32(&r4tst->rtsdctl, (val << RTSDCTL_ENT_DLY_SHIFT) |
index d6d067fbee970e49670e92746145566ed6925332..ca60bb8114f22a4df6f175b0f5a942e51e3cb45d 100644 (file)
@@ -121,6 +121,45 @@ static bool cxl_is_security_command(u16 opcode)
        return false;
 }
 
+static void cxl_set_security_cmd_enabled(struct cxl_security_state *security,
+                                        u16 opcode)
+{
+       switch (opcode) {
+       case CXL_MBOX_OP_SANITIZE:
+               set_bit(CXL_SEC_ENABLED_SANITIZE, security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_SECURE_ERASE:
+               set_bit(CXL_SEC_ENABLED_SECURE_ERASE,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_GET_SECURITY_STATE:
+               set_bit(CXL_SEC_ENABLED_GET_SECURITY_STATE,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_SET_PASSPHRASE:
+               set_bit(CXL_SEC_ENABLED_SET_PASSPHRASE,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_DISABLE_PASSPHRASE:
+               set_bit(CXL_SEC_ENABLED_DISABLE_PASSPHRASE,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_UNLOCK:
+               set_bit(CXL_SEC_ENABLED_UNLOCK, security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_FREEZE_SECURITY:
+               set_bit(CXL_SEC_ENABLED_FREEZE_SECURITY,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE:
+               set_bit(CXL_SEC_ENABLED_PASSPHRASE_SECURE_ERASE,
+                       security->enabled_cmds);
+               break;
+       default:
+               break;
+       }
+}
+
 static bool cxl_is_poison_command(u16 opcode)
 {
 #define CXL_MBOX_OP_POISON_CMDS 0x43
@@ -677,7 +716,8 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
                u16 opcode = le16_to_cpu(cel_entry[i].opcode);
                struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
 
-               if (!cmd && !cxl_is_poison_command(opcode)) {
+               if (!cmd && (!cxl_is_poison_command(opcode) ||
+                            !cxl_is_security_command(opcode))) {
                        dev_dbg(dev,
                                "Opcode 0x%04x unsupported by driver\n", opcode);
                        continue;
@@ -689,6 +729,9 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
                if (cxl_is_poison_command(opcode))
                        cxl_set_poison_cmd_enabled(&mds->poison, opcode);
 
+               if (cxl_is_security_command(opcode))
+                       cxl_set_security_cmd_enabled(&mds->security, opcode);
+
                dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode);
        }
 }
index f99e7ec3cc40e8179d91f1765b82f22623236041..14b547c07f547602fd243a4ca1bd0097c751948e 100644 (file)
@@ -477,9 +477,28 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = {
        .attrs = cxl_memdev_pmem_attributes,
 };
 
+static umode_t cxl_memdev_security_visible(struct kobject *kobj,
+                                          struct attribute *a, int n)
+{
+       struct device *dev = kobj_to_dev(kobj);
+       struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+       struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+
+       if (a == &dev_attr_security_sanitize.attr &&
+           !test_bit(CXL_SEC_ENABLED_SANITIZE, mds->security.enabled_cmds))
+               return 0;
+
+       if (a == &dev_attr_security_erase.attr &&
+           !test_bit(CXL_SEC_ENABLED_SECURE_ERASE, mds->security.enabled_cmds))
+               return 0;
+
+       return a->mode;
+}
+
 static struct attribute_group cxl_memdev_security_attribute_group = {
        .name = "security",
        .attrs = cxl_memdev_security_attributes,
+       .is_visible = cxl_memdev_security_visible,
 };
 
 static const struct attribute_group *cxl_memdev_attribute_groups[] = {
index 4991133285867199b9f24db7ca815c19b56b8063..706f8a6d1ef43c78dfdebd62cd5b55347186fdbb 100644 (file)
@@ -244,6 +244,19 @@ enum poison_cmd_enabled_bits {
        CXL_POISON_ENABLED_MAX
 };
 
+/* Device enabled security commands */
+enum security_cmd_enabled_bits {
+       CXL_SEC_ENABLED_SANITIZE,
+       CXL_SEC_ENABLED_SECURE_ERASE,
+       CXL_SEC_ENABLED_GET_SECURITY_STATE,
+       CXL_SEC_ENABLED_SET_PASSPHRASE,
+       CXL_SEC_ENABLED_DISABLE_PASSPHRASE,
+       CXL_SEC_ENABLED_UNLOCK,
+       CXL_SEC_ENABLED_FREEZE_SECURITY,
+       CXL_SEC_ENABLED_PASSPHRASE_SECURE_ERASE,
+       CXL_SEC_ENABLED_MAX
+};
+
 /**
  * struct cxl_poison_state - Driver poison state info
  *
@@ -346,6 +359,7 @@ struct cxl_fw_state {
  * struct cxl_security_state - Device security state
  *
  * @state: state of last security operation
+ * @enabled_cmds: All security commands enabled in the CEL
  * @poll: polling for sanitization is enabled, device has no mbox irq support
  * @poll_tmo_secs: polling timeout
  * @poll_dwork: polling work item
@@ -353,6 +367,7 @@ struct cxl_fw_state {
  */
 struct cxl_security_state {
        unsigned long state;
+       DECLARE_BITMAP(enabled_cmds, CXL_SEC_ENABLED_MAX);
        bool poll;
        int poll_tmo_secs;
        struct delayed_work poll_dwork;
@@ -434,6 +449,7 @@ struct cxl_dev_state {
  * @next_persistent_bytes: persistent capacity change pending device reset
  * @event: event log driver state
  * @poison: poison driver state info
+ * @security: security driver state info
  * @fw: firmware upload / activation state
  * @mbox_send: @dev specific transport for transmitting mailbox commands
  *
index 644c188d6a1103ebf6877337dc418fbffe7ea754..08fdd0e2ed1bf01a4be5baf462fabb32dd5b88d3 100644 (file)
@@ -211,6 +211,7 @@ config FSL_DMA
 config FSL_EDMA
        tristate "Freescale eDMA engine support"
        depends on OF
+       depends on HAS_IOMEM
        select DMA_ENGINE
        select DMA_VIRTUAL_CHANNELS
        help
@@ -280,6 +281,7 @@ config IMX_SDMA
 
 config INTEL_IDMA64
        tristate "Intel integrated DMA 64-bit support"
+       depends on HAS_IOMEM
        select DMA_ENGINE
        select DMA_VIRTUAL_CHANNELS
        help
index 5abbcc61c5288c2251ae32816f8bd23adcb1264e..9a15f0d12c79989006dd78110d51f83b433b3b9d 100644 (file)
@@ -384,9 +384,7 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
        wq->threshold = 0;
        wq->priority = 0;
        wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
-       clear_bit(WQ_FLAG_DEDICATED, &wq->flags);
-       clear_bit(WQ_FLAG_BLOCK_ON_FAULT, &wq->flags);
-       clear_bit(WQ_FLAG_ATS_DISABLE, &wq->flags);
+       wq->flags = 0;
        memset(wq->name, 0, WQ_NAME_SIZE);
        wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER;
        idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH);
index ebd8733f72ad43c93a5909f7bb60720cc3e6adc0..9413fad08a60ca0503c87bda291c94dbb01a0c6b 100644 (file)
@@ -190,7 +190,13 @@ static int mcf_edma_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       chans = pdata->dma_channels;
+       if (!pdata->dma_channels) {
+               dev_info(&pdev->dev, "setting default channel number to 64");
+               chans = 64;
+       } else {
+               chans = pdata->dma_channels;
+       }
+
        len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans;
        mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
        if (!mcf_edma)
@@ -202,11 +208,6 @@ static int mcf_edma_probe(struct platform_device *pdev)
        mcf_edma->drvdata = &mcf_data;
        mcf_edma->big_endian = 1;
 
-       if (!mcf_edma->n_chans) {
-               dev_info(&pdev->dev, "setting default channel number to 64");
-               mcf_edma->n_chans = 64;
-       }
-
        mutex_init(&mcf_edma->fsl_edma_mutex);
 
        mcf_edma->membase = devm_platform_ioremap_resource(pdev, 0);
index 95a462a1f5111ddaffb688a50cfda6cf0dfe1740..b6e0ac8314e5cd278a0d3555805146a21bd206b3 100644 (file)
@@ -192,7 +192,7 @@ struct owl_dma_pchan {
 };
 
 /**
- * struct owl_dma_pchan - Wrapper for DMA ENGINE channel
+ * struct owl_dma_vchan - Wrapper for DMA ENGINE channel
  * @vc: wrapped virtual channel
  * @pchan: the physical channel utilized by this channel
  * @txd: active transaction on this channel
index b4731fe6bbc14fc7360723726b535a6194383429..3cf0b38387ae5604adf7fbf07574444171c21043 100644 (file)
@@ -403,6 +403,12 @@ enum desc_status {
         * of a channel can be BUSY at any time.
         */
        BUSY,
+       /*
+        * Pause was called while descriptor was BUSY. Due to hardware
+        * limitations, only termination is possible for descriptors
+        * that have been paused.
+        */
+       PAUSED,
        /*
         * Sitting on the channel work_list but xfer done
         * by PL330 core
@@ -2041,7 +2047,7 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
        list_for_each_entry(desc, &pch->work_list, node) {
 
                /* If already submitted */
-               if (desc->status == BUSY)
+               if (desc->status == BUSY || desc->status == PAUSED)
                        continue;
 
                ret = pl330_submit_req(pch->thread, desc);
@@ -2326,6 +2332,7 @@ static int pl330_pause(struct dma_chan *chan)
 {
        struct dma_pl330_chan *pch = to_pchan(chan);
        struct pl330_dmac *pl330 = pch->dmac;
+       struct dma_pl330_desc *desc;
        unsigned long flags;
 
        pm_runtime_get_sync(pl330->ddma.dev);
@@ -2335,6 +2342,10 @@ static int pl330_pause(struct dma_chan *chan)
        _stop(pch->thread);
        spin_unlock(&pl330->lock);
 
+       list_for_each_entry(desc, &pch->work_list, node) {
+               if (desc->status == BUSY)
+                       desc->status = PAUSED;
+       }
        spin_unlock_irqrestore(&pch->lock, flags);
        pm_runtime_mark_last_busy(pl330->ddma.dev);
        pm_runtime_put_autosuspend(pl330->ddma.dev);
@@ -2425,7 +2436,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                else if (running && desc == running)
                        transferred =
                                pl330_get_current_xferred_count(pch, desc);
-               else if (desc->status == BUSY)
+               else if (desc->status == BUSY || desc->status == PAUSED)
                        /*
                         * Busy but not running means either just enqueued,
                         * or finished and not yet marked done
@@ -2442,6 +2453,9 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                        case DONE:
                                ret = DMA_COMPLETE;
                                break;
+                       case PAUSED:
+                               ret = DMA_PAUSED;
+                               break;
                        case PREP:
                        case BUSY:
                                ret = DMA_IN_PROGRESS;
index 93ee298d52b894f1a7200844168c2baaf0406763..e0bfd129d563f3687a55e298d30157595245c3cf 100644 (file)
@@ -668,6 +668,8 @@ static int xdma_set_vector_reg(struct xdma_device *xdev, u32 vec_tbl_start,
                        val |= irq_start << shift;
                        irq_start++;
                        irq_num--;
+                       if (!irq_num)
+                               break;
                }
 
                /* write IRQ register */
@@ -715,7 +717,7 @@ static int xdma_irq_init(struct xdma_device *xdev)
                ret = request_irq(irq, xdma_channel_isr, 0,
                                  "xdma-c2h-channel", &xdev->c2h_chans[j]);
                if (ret) {
-                       xdma_err(xdev, "H2C channel%d request irq%d failed: %d",
+                       xdma_err(xdev, "C2H channel%d request irq%d failed: %d",
                                 j, irq, ret);
                        goto failed_init_c2h;
                }
@@ -892,7 +894,7 @@ static int xdma_probe(struct platform_device *pdev)
        }
 
        reg_base = devm_ioremap_resource(&pdev->dev, res);
-       if (!reg_base) {
+       if (IS_ERR(reg_base)) {
                xdma_err(xdev, "ioremap failed");
                goto failed;
        }
index 1efa5e9392c4214439f9bb9100e2fbff12e8e839..19246ed1f01ff7cc3ea7346402c32e02b57b336a 100644 (file)
@@ -166,8 +166,10 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                return -ENOMEM;
 
        shmem = of_parse_phandle(cdev->of_node, "shmem", idx);
-       if (!of_device_is_compatible(shmem, "arm,scmi-shmem"))
+       if (!of_device_is_compatible(shmem, "arm,scmi-shmem")) {
+               of_node_put(shmem);
                return -ENXIO;
+       }
 
        ret = of_address_to_resource(shmem, 0, &res);
        of_node_put(shmem);
index 6971dcf72fb998425655865fd6ccf4e1ecb44976..0493aa3c12bf5363e02c1ecc9b2520d1bd8b3d67 100644 (file)
@@ -818,10 +818,13 @@ static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp,
         * before sending it with a single RAW xfer.
         */
        if (rd->tx_size < rd->tx_req_size) {
-               size_t cnt;
+               ssize_t cnt;
 
                cnt = simple_write_to_buffer(rd->tx.buf, rd->tx.len, ppos,
                                             buf, count);
+               if (cnt < 0)
+                       return cnt;
+
                rd->tx_size += cnt;
                if (cnt < count)
                        return cnt;
index 621c37efe3ec49a2d28e15b9ff18718c614f46b4..c193516a254d9e056ae34116e3c1d10a048d01cb 100644 (file)
@@ -40,6 +40,7 @@
 /**
  * struct scmi_smc - Structure representing a SCMI smc transport
  *
+ * @irq: An optional IRQ for completion
  * @cinfo: SCMI channel info
  * @shmem: Transmit/Receive shared memory area
  * @shmem_lock: Lock to protect access to Tx/Rx shared memory area.
@@ -52,6 +53,7 @@
  */
 
 struct scmi_smc {
+       int irq;
        struct scmi_chan_info *cinfo;
        struct scmi_shared_mem __iomem *shmem;
        /* Protect access to shmem area */
@@ -127,7 +129,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
        struct resource res;
        struct device_node *np;
        u32 func_id;
-       int ret, irq;
+       int ret;
 
        if (!tx)
                return -ENODEV;
@@ -137,8 +139,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                return -ENOMEM;
 
        np = of_parse_phandle(cdev->of_node, "shmem", 0);
-       if (!of_device_is_compatible(np, "arm,scmi-shmem"))
+       if (!of_device_is_compatible(np, "arm,scmi-shmem")) {
+               of_node_put(np);
                return -ENXIO;
+       }
 
        ret = of_address_to_resource(np, 0, &res);
        of_node_put(np);
@@ -167,11 +171,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
         * completion of a message is signaled by an interrupt rather than by
         * the return of the SMC call.
         */
-       irq = of_irq_get_byname(cdev->of_node, "a2p");
-       if (irq > 0) {
-               ret = devm_request_irq(dev, irq, smc_msg_done_isr,
-                                      IRQF_NO_SUSPEND,
-                                      dev_name(dev), scmi_info);
+       scmi_info->irq = of_irq_get_byname(cdev->of_node, "a2p");
+       if (scmi_info->irq > 0) {
+               ret = request_irq(scmi_info->irq, smc_msg_done_isr,
+                                 IRQF_NO_SUSPEND, dev_name(dev), scmi_info);
                if (ret) {
                        dev_err(dev, "failed to setup SCMI smc irq\n");
                        return ret;
@@ -193,6 +196,10 @@ static int smc_chan_free(int id, void *p, void *data)
        struct scmi_chan_info *cinfo = p;
        struct scmi_smc *scmi_info = cinfo->transport_info;
 
+       /* Ignore any possible further reception on the IRQ path */
+       if (scmi_info->irq > 0)
+               free_irq(scmi_info->irq, scmi_info);
+
        cinfo->transport_info = NULL;
        scmi_info->cinfo = NULL;
 
index 890eb454599a33ba5100a0e299eaed004d1d88ee..1990263fbba0e026bdb25017856a72b512c52ece 100644 (file)
@@ -34,7 +34,6 @@ static struct soc_device_attribute *soc_dev_attr;
 
 static int __init smccc_soc_init(void)
 {
-       struct arm_smccc_res res;
        int soc_id_rev, soc_id_version;
        static char soc_id_str[20], soc_id_rev_str[12];
        static char soc_id_jep106_id_str[12];
@@ -49,13 +48,13 @@ static int __init smccc_soc_init(void)
        }
 
        if (soc_id_version < 0) {
-               pr_err("ARCH_SOC_ID(0) returned error: %lx\n", res.a0);
+               pr_err("Invalid SoC Version: %x\n", soc_id_version);
                return -EINVAL;
        }
 
        soc_id_rev = arm_smccc_get_soc_id_revision();
        if (soc_id_rev < 0) {
-               pr_err("ARCH_SOC_ID(1) returned error: %lx\n", res.a0);
+               pr_err("Invalid SoC Revision: %x\n", soc_id_rev);
                return -EINVAL;
        }
 
index 8b49b0abacd518448ab7a49629a413d4388a35c1..f1f6f1c329877e9526f6a3387b87498fce940fd4 100644 (file)
@@ -429,6 +429,7 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
        gc->set_config = gpio_sim_set_config;
        gc->to_irq = gpio_sim_to_irq;
        gc->free = gpio_sim_free;
+       gc->can_sleep = true;
 
        ret = devm_gpiochip_add_data(dev, gc, chip);
        if (ret)
index e73885a4dc32871ed634dc9548b1f63fd3ca5ed8..afb42a8e916fe11e9e0cb50e60d7d35c783386e6 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-#define WS16C48_EXTENT 10
+#define WS16C48_EXTENT 11
 #define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT)
 
 static unsigned int base[MAX_NUM_WS16C48];
index 530dfd19d7b52e2a04372c64de32dde7949d8c77..50503a4525eb03ce95325e5d9441b8efeca29515 100644 (file)
@@ -515,8 +515,9 @@ static ssize_t unexport_store(const struct class *class,
         * they may be undone on its behalf too.
         */
        if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {
-               status = 0;
+               gpiod_unexport(desc);
                gpiod_free(desc);
+               status = 0;
        }
 done:
        if (status)
@@ -781,8 +782,10 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
        mutex_unlock(&sysfs_lock);
 
        /* unregister gpiod class devices owned by sysfs */
-       for_each_gpio_desc_with_flag(chip, desc, FLAG_SYSFS)
+       for_each_gpio_desc_with_flag(chip, desc, FLAG_SYSFS) {
+               gpiod_unexport(desc);
                gpiod_free(desc);
+       }
 }
 
 static int __init gpiolib_sysfs_init(void)
index 251c875b5c34cc563e113cf1f4ec257b31a2c213..76e0c38026c3e94b87566a35eb98b6bc40fb2061 100644 (file)
@@ -2167,12 +2167,18 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
 
 void gpiod_free(struct gpio_desc *desc)
 {
-       if (desc && desc->gdev && gpiod_free_commit(desc)) {
-               module_put(desc->gdev->owner);
-               gpio_device_put(desc->gdev);
-       } else {
+       /*
+        * We must not use VALIDATE_DESC_VOID() as the underlying gdev->chip
+        * may already be NULL but we still want to put the references.
+        */
+       if (!desc)
+               return;
+
+       if (!gpiod_free_commit(desc))
                WARN_ON(extra_checks);
-       }
+
+       module_put(desc->gdev->owner);
+       gpio_device_put(desc->gdev);
 }
 
 /**
index a3b86b86dc477ca09cd3391cb332786c764d8008..6dc950c1b68933cbedfadf8034e736168e3595c3 100644 (file)
@@ -1296,6 +1296,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
 void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
 int amdgpu_device_pci_reset(struct amdgpu_device *adev);
 bool amdgpu_device_need_post(struct amdgpu_device *adev);
+bool amdgpu_sg_display_supported(struct amdgpu_device *adev);
 bool amdgpu_device_pcie_dynamic_switching_supported(void);
 bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev);
 bool amdgpu_device_aspm_support_quirk(void);
index 040f4cb6ab2d0fb20ac7d97af1a7d6d10f246c03..fb78a8f4758792498e5c3d8fe69543c86afcfa11 100644 (file)
@@ -295,7 +295,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
 
        if (!p->gang_size) {
                ret = -EINVAL;
-               goto free_partial_kdata;
+               goto free_all_kdata;
        }
 
        for (i = 0; i < p->gang_size; ++i) {
index a2cdde0ca0a72f42ef7cc4e2929fda910c066548..6238701cde237b623ac0201bc76f53d97132f726 100644 (file)
@@ -1458,6 +1458,32 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
        return true;
 }
 
+/*
+ * On APUs with >= 64GB white flickering has been observed w/ SG enabled.
+ * Disable S/G on such systems until we have a proper fix.
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/2354
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/2735
+ */
+bool amdgpu_sg_display_supported(struct amdgpu_device *adev)
+{
+       switch (amdgpu_sg_display) {
+       case -1:
+               break;
+       case 0:
+               return false;
+       case 1:
+               return true;
+       default:
+               return false;
+       }
+       if ((totalram_pages() << (PAGE_SHIFT - 10)) +
+           (adev->gmc.real_vram_size / 1024) >= 64000000) {
+               DRM_WARN("Disabling S/G due to >=64GB RAM\n");
+               return false;
+       }
+       return true;
+}
+
 /*
  * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic
  * speed switching. Until we have confirmation from Intel that a specific host
@@ -3696,10 +3722,11 @@ static void amdgpu_device_set_mcbp(struct amdgpu_device *adev)
 {
        if (amdgpu_mcbp == 1)
                adev->gfx.mcbp = true;
-
-       if ((adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 0, 0)) &&
-           (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 0, 0)) &&
-           adev->gfx.num_gfx_rings)
+       else if (amdgpu_mcbp == 0)
+               adev->gfx.mcbp = false;
+       else if ((adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 0, 0)) &&
+                (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 0, 0)) &&
+                adev->gfx.num_gfx_rings)
                adev->gfx.mcbp = true;
 
        if (amdgpu_sriov_vf(adev))
@@ -4367,6 +4394,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
                drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
 
        cancel_delayed_work_sync(&adev->delayed_init_work);
+       flush_delayed_work(&adev->gfx.gfx_off_delay_work);
 
        amdgpu_ras_suspend(adev);
 
index c694b41f6461b5e1495906a1d3bdd1af6a36b46f..7537f5aa76f0c08f8385566fa0f25cfd3d692a45 100644 (file)
@@ -551,6 +551,41 @@ int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_fence_need_ring_interrupt_restore - helper function to check whether
+ * fence driver interrupts need to be restored.
+ *
+ * @ring: ring that to be checked
+ *
+ * Interrupts for rings that belong to GFX IP don't need to be restored
+ * when the target power state is s0ix.
+ *
+ * Return true if need to restore interrupts, false otherwise.
+ */
+static bool amdgpu_fence_need_ring_interrupt_restore(struct amdgpu_ring *ring)
+{
+       struct amdgpu_device *adev = ring->adev;
+       bool is_gfx_power_domain = false;
+
+       switch (ring->funcs->type) {
+       case AMDGPU_RING_TYPE_SDMA:
+       /* SDMA 5.x+ is part of GFX power domain so it's covered by GFXOFF */
+               if (adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(5, 0, 0))
+                       is_gfx_power_domain = true;
+               break;
+       case AMDGPU_RING_TYPE_GFX:
+       case AMDGPU_RING_TYPE_COMPUTE:
+       case AMDGPU_RING_TYPE_KIQ:
+       case AMDGPU_RING_TYPE_MES:
+               is_gfx_power_domain = true;
+               break;
+       default:
+               break;
+       }
+
+       return !(adev->in_s0ix && is_gfx_power_domain);
+}
+
 /**
  * amdgpu_fence_driver_hw_fini - tear down the fence driver
  * for all possible rings.
@@ -579,7 +614,8 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev)
                        amdgpu_fence_driver_force_completion(ring);
 
                if (!drm_dev_is_unplugged(adev_to_drm(adev)) &&
-                   ring->fence_drv.irq_src)
+                   ring->fence_drv.irq_src &&
+                   amdgpu_fence_need_ring_interrupt_restore(ring))
                        amdgpu_irq_put(adev, ring->fence_drv.irq_src,
                                       ring->fence_drv.irq_type);
 
@@ -655,7 +691,8 @@ void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev)
                        continue;
 
                /* enable the interrupt */
-               if (ring->fence_drv.irq_src)
+               if (ring->fence_drv.irq_src &&
+                   amdgpu_fence_need_ring_interrupt_restore(ring))
                        amdgpu_irq_get(adev, ring->fence_drv.irq_src,
                                       ring->fence_drv.irq_type);
        }
index a33d4bc34cee746cdee7e70103190fee0aa9f2cd..fd81b04559d4992d11732eecae35b8c5a0b43612 100644 (file)
@@ -692,15 +692,8 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable)
 
                if (adev->gfx.gfx_off_req_count == 0 &&
                    !adev->gfx.gfx_off_state) {
-                       /* If going to s2idle, no need to wait */
-                       if (adev->in_s0ix) {
-                               if (!amdgpu_dpm_set_powergating_by_smu(adev,
-                                               AMD_IP_BLOCK_TYPE_GFX, true))
-                                       adev->gfx.gfx_off_state = true;
-                       } else {
-                               schedule_delayed_work(&adev->gfx.gfx_off_delay_work,
+                       schedule_delayed_work(&adev->gfx.gfx_off_delay_work,
                                              delay);
-                       }
                }
        } else {
                if (adev->gfx.gfx_off_req_count == 0) {
index b779ee4bbaa7b36273247638de6f3f478e98a0d4..e1ee1c7117fb93024ddb17628a3f30824daba417 100644 (file)
@@ -397,7 +397,7 @@ void amdgpu_sw_ring_ib_begin(struct amdgpu_ring *ring)
        struct amdgpu_ring_mux *mux = &adev->gfx.muxer;
 
        WARN_ON(!ring->is_sw_ring);
-       if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT) {
+       if (adev->gfx.mcbp && ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT) {
                if (amdgpu_mcbp_scan(mux) > 0)
                        amdgpu_mcbp_trigger_preempt(mux);
                return;
index 9c9cca1294989c25f7c3d251e34be478e9391bc5..565a1fa436d4b8032e83cf6d7dc3863480a1d56d 100644 (file)
@@ -239,8 +239,13 @@ static int amdgpu_xcp_dev_alloc(struct amdgpu_device *adev)
 
        for (i = 1; i < MAX_XCP; i++) {
                ret = amdgpu_xcp_drm_dev_alloc(&p_ddev);
-               if (ret)
+               if (ret == -ENOSPC) {
+                       dev_warn(adev->dev,
+                       "Skip xcp node #%d when out of drm node resource.", i);
+                       return 0;
+               } else if (ret) {
                        return ret;
+               }
 
                /* Redirect all IOCTLs to the primary device */
                adev->xcp_mgr->xcp[i].rdev = p_ddev->render->dev;
@@ -328,6 +333,9 @@ int amdgpu_xcp_dev_register(struct amdgpu_device *adev,
                return 0;
 
        for (i = 1; i < MAX_XCP; i++) {
+               if (!adev->xcp_mgr->xcp[i].ddev)
+                       break;
+
                ret = drm_dev_register(adev->xcp_mgr->xcp[i].ddev, ent->driver_data);
                if (ret)
                        return ret;
@@ -345,6 +353,9 @@ void amdgpu_xcp_dev_unplug(struct amdgpu_device *adev)
                return;
 
        for (i = 1; i < MAX_XCP; i++) {
+               if (!adev->xcp_mgr->xcp[i].ddev)
+                       break;
+
                p_ddev = adev->xcp_mgr->xcp[i].ddev;
                drm_dev_unplug(p_ddev);
                p_ddev->render->dev = adev->xcp_mgr->xcp[i].rdev;
index 3a7af59e83ca11ea1409e8903899d302b5b3187c..0451533ddde41eb2b54972cde098368746ee76fa 100644 (file)
@@ -471,8 +471,12 @@ static void gfx_v11_0_check_fw_cp_gfx_shadow(struct amdgpu_device *adev)
        case IP_VERSION(11, 0, 3):
                if ((adev->gfx.me_fw_version >= 1505) &&
                    (adev->gfx.pfp_fw_version >= 1600) &&
-                   (adev->gfx.mec_fw_version >= 512))
-                       adev->gfx.cp_gfx_shadow = true;
+                   (adev->gfx.mec_fw_version >= 512)) {
+                       if (amdgpu_sriov_vf(adev))
+                               adev->gfx.cp_gfx_shadow = true;
+                       else
+                               adev->gfx.cp_gfx_shadow = false;
+               }
                break;
        default:
                adev->gfx.cp_gfx_shadow = false;
index e1a392bcea70d3ae99b1a504a118a9728c43e736..af5685f4cb344a767fb5e255d26efcf0685ee425 100644 (file)
@@ -137,14 +137,15 @@ static int psp_v13_0_wait_for_bootloader(struct psp_context *psp)
        int ret;
        int retry_loop;
 
+       /* Wait for bootloader to signify that it is ready having bit 31 of
+        * C2PMSG_35 set to 1. All other bits are expected to be cleared.
+        * If there is an error in processing command, bits[7:0] will be set.
+        * This is applicable for PSP v13.0.6 and newer.
+        */
        for (retry_loop = 0; retry_loop < 10; retry_loop++) {
-               /* Wait for bootloader to signify that is
-                   ready having bit 31 of C2PMSG_35 set to 1 */
-               ret = psp_wait_for(psp,
-                                  SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
-                                  0x80000000,
-                                  0x80000000,
-                                  false);
+               ret = psp_wait_for(
+                       psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
+                       0x80000000, 0xffffffff, false);
 
                if (ret == 0)
                        return 0;
index 49f40d9f16e8652e79582d13d5bcc95e26f4a5ad..f5a6f562e2a80392ca135000f3ab579d0114aa2b 100644 (file)
@@ -1543,11 +1543,7 @@ static bool kfd_ignore_crat(void)
        if (ignore_crat)
                return true;
 
-#ifndef KFD_SUPPORT_IOMMU_V2
        ret = true;
-#else
-       ret = false;
-#endif
 
        return ret;
 }
index 0b3dc754e06ba264bf25835f33c7607a6fae4dfe..a53e0757fe643d1247f3c396107f60dea89c4492 100644 (file)
@@ -194,11 +194,6 @@ static void kfd_device_info_init(struct kfd_dev *kfd,
 
                kfd_device_info_set_event_interrupt_class(kfd);
 
-               /* Raven */
-               if (gc_version == IP_VERSION(9, 1, 0) ||
-                   gc_version == IP_VERSION(9, 2, 2))
-                       kfd->device_info.needs_iommu_device = true;
-
                if (gc_version < IP_VERSION(11, 0, 0)) {
                        /* Navi2x+, Navi1x+ */
                        if (gc_version == IP_VERSION(10, 3, 6))
@@ -233,10 +228,6 @@ static void kfd_device_info_init(struct kfd_dev *kfd,
                    asic_type != CHIP_TONGA)
                        kfd->device_info.supports_cwsr = true;
 
-               if (asic_type == CHIP_KAVERI ||
-                   asic_type == CHIP_CARRIZO)
-                       kfd->device_info.needs_iommu_device = true;
-
                if (asic_type != CHIP_HAWAII && !vf)
                        kfd->device_info.needs_pci_atomics = true;
        }
@@ -249,7 +240,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
        uint32_t gfx_target_version = 0;
 
        switch (adev->asic_type) {
-#ifdef KFD_SUPPORT_IOMMU_V2
 #ifdef CONFIG_DRM_AMDGPU_CIK
        case CHIP_KAVERI:
                gfx_target_version = 70000;
@@ -262,7 +252,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
                if (!vf)
                        f2g = &gfx_v8_kfd2kgd;
                break;
-#endif
 #ifdef CONFIG_DRM_AMDGPU_CIK
        case CHIP_HAWAII:
                gfx_target_version = 70001;
@@ -298,7 +287,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
                        gfx_target_version = 90000;
                        f2g = &gfx_v9_kfd2kgd;
                        break;
-#ifdef KFD_SUPPORT_IOMMU_V2
                /* Raven */
                case IP_VERSION(9, 1, 0):
                case IP_VERSION(9, 2, 2):
@@ -306,7 +294,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
                        if (!vf)
                                f2g = &gfx_v9_kfd2kgd;
                        break;
-#endif
                /* Vega12 */
                case IP_VERSION(9, 2, 1):
                        gfx_target_version = 90004;
index 2df153828ff43b424370d96c065fe039ad1dd943..01192f5abe462bc525f05ed8df9b68488c3deba1 100644 (file)
@@ -2538,18 +2538,12 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
        }
 
        switch (dev->adev->asic_type) {
-       case CHIP_CARRIZO:
-               device_queue_manager_init_vi(&dqm->asic_ops);
-               break;
-
        case CHIP_KAVERI:
-               device_queue_manager_init_cik(&dqm->asic_ops);
-               break;
-
        case CHIP_HAWAII:
                device_queue_manager_init_cik_hawaii(&dqm->asic_ops);
                break;
 
+       case CHIP_CARRIZO:
        case CHIP_TONGA:
        case CHIP_FIJI:
        case CHIP_POLARIS10:
index 61fc62f3e0034a1b129ddb4ad298cb2667fa556d..4a17bb7c7b27d7a81f6eb744ad49d59838a71f41 100644 (file)
@@ -1965,7 +1965,14 @@ int kfd_topology_add_device(struct kfd_node *gpu)
        const char *asic_name = amdgpu_asic_name[gpu->adev->asic_type];
 
        gpu_id = kfd_generate_gpu_id(gpu);
-       pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
+       if (gpu->xcp && !gpu->xcp->ddev) {
+               dev_warn(gpu->adev->dev,
+               "Won't add GPU (ID: 0x%x) to topology since it has no drm node assigned.",
+               gpu_id);
+               return 0;
+       } else {
+               pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
+       }
 
        /* Check to see if this gpu device exists in the topology_device_list.
         * If so, assign the gpu to that device,
index 0fa739fd6a9ca5329f117cf9a4e6219fe50b4a3a..e5554a36e8c8b2c7d8e43bc9b19c722941dfad83 100644 (file)
@@ -1638,9 +1638,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
                }
                break;
        }
-       if (init_data.flags.gpu_vm_support &&
-           (amdgpu_sg_display == 0))
-               init_data.flags.gpu_vm_support = false;
+       if (init_data.flags.gpu_vm_support)
+               init_data.flags.gpu_vm_support = amdgpu_sg_display_supported(adev);
 
        if (init_data.flags.gpu_vm_support)
                adev->mode_info.gpu_vm_support = true;
index 9bc86deac9e8e3867b9df7cece016f515ec0987f..b885c39bd16ba212e10323db51a0e67d1388a1af 100644 (file)
@@ -1320,7 +1320,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
                if (computed_streams[i])
                        continue;
 
-               if (!res_pool->funcs->remove_stream_from_ctx ||
+               if (res_pool->funcs->remove_stream_from_ctx &&
                    res_pool->funcs->remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
                        return -EINVAL;
 
index 20d4d08a6a2f3c9d2190f3a5efd4d97db8dfe0c3..6966420dfbac3980d271680b9b2e0f710ec9ce10 100644 (file)
@@ -777,7 +777,8 @@ void dce110_edp_wait_for_hpd_ready(
        dal_gpio_destroy_irq(&hpd);
 
        /* ensure that the panel is detected */
-       ASSERT(edp_hpd_high);
+       if (!edp_hpd_high)
+               DC_LOG_DC("%s: wait timed out!\n", __func__);
 }
 
 void dce110_edp_power_control(
index 4cc8de2627ce92bee5a3b7f98e81b9f2b6670d96..9f2e24398cd77357cf6459591cbf0e02948625ca 100644 (file)
@@ -712,7 +712,7 @@ static const struct dc_debug_options debug_defaults_drv = {
                .timing_trace = false,
                .clock_trace = true,
                .disable_pplib_clock_request = true,
-               .pipe_split_policy = MPC_SPLIT_DYNAMIC,
+               .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP,
                .force_single_disp_pipe_split = false,
                .disable_dcc = DCC_ENABLE,
                .vsr_support = true,
index e5b7ef7422b833ea5b0301f024784cb3e906accc..50dc834046446ae72647d722be59b519e4d35082 100644 (file)
@@ -357,8 +357,11 @@ void dpp3_set_cursor_attributes(
        int cur_rom_en = 0;
 
        if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA ||
-               color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA)
-               cur_rom_en = 1;
+               color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) {
+               if (cursor_attributes->attribute_flags.bits.ENABLE_CURSOR_DEGAMMA) {
+                       cur_rom_en = 1;
+               }
+       }
 
        REG_UPDATE_3(CURSOR0_CONTROL,
                        CUR0_MODE, color_format,
index ce41a8309582c91dca9d901df46691ad36079560..222af2fae745852bfa00b7fd41ae603f1f8e5414 100644 (file)
@@ -1581,9 +1581,9 @@ static int smu_disable_dpms(struct smu_context *smu)
 
        /*
         * For SMU 13.0.4/11, PMFW will handle the features disablement properly
-        * for gpu reset case. Driver involvement is unnecessary.
+        * for gpu reset and S0i3 cases. Driver involvement is unnecessary.
         */
-       if (amdgpu_in_reset(adev)) {
+       if (amdgpu_in_reset(adev) || adev->in_s0ix) {
                switch (adev->ip_versions[MP1_HWIP][0]) {
                case IP_VERSION(13, 0, 4):
                case IP_VERSION(13, 0, 11):
index 0cda3b276f6115a1a4a18a370966943d0db133d5..f0800c0c5168c935be6fbd7af1a10282729fccc1 100644 (file)
@@ -588,7 +588,9 @@ err0_out:
        return -ENOMEM;
 }
 
-static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *smu)
+static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *smu,
+                                                          bool use_metrics_v3,
+                                                          bool use_metrics_v2)
 {
        struct smu_table_context *smu_table= &smu->smu_table;
        SmuMetricsExternal_t *metrics_ext =
@@ -596,13 +598,11 @@ static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *s
        uint32_t throttler_status = 0;
        int i;
 
-       if ((smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 7)) &&
-            (smu->smc_fw_version >= 0x3A4900)) {
+       if (use_metrics_v3) {
                for (i = 0; i < THROTTLER_COUNT; i++)
                        throttler_status |=
                                (metrics_ext->SmuMetrics_V3.ThrottlingPercentage[i] ? 1U << i : 0);
-       } else if ((smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 7)) &&
-            (smu->smc_fw_version >= 0x3A4300)) {
+       } else if (use_metrics_v2) {
                for (i = 0; i < THROTTLER_COUNT; i++)
                        throttler_status |=
                                (metrics_ext->SmuMetrics_V2.ThrottlingPercentage[i] ? 1U << i : 0);
@@ -864,7 +864,7 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
                        metrics->TemperatureVrSoc) * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
                break;
        case METRICS_THROTTLER_STATUS:
-               *value = sienna_cichlid_get_throttler_status_locked(smu);
+               *value = sienna_cichlid_get_throttler_status_locked(smu, use_metrics_v3, use_metrics_v2);
                break;
        case METRICS_CURR_FANSPEED:
                *value = use_metrics_v3 ? metrics_v3->CurrFanSpeed :
@@ -4017,7 +4017,7 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu,
        gpu_metrics->current_dclk1 = use_metrics_v3 ? metrics_v3->CurrClock[PPCLK_DCLK_1] :
                use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_1] : metrics->CurrClock[PPCLK_DCLK_1];
 
-       gpu_metrics->throttle_status = sienna_cichlid_get_throttler_status_locked(smu);
+       gpu_metrics->throttle_status = sienna_cichlid_get_throttler_status_locked(smu, use_metrics_v3, use_metrics_v2);
        gpu_metrics->indep_throttle_status =
                        smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status,
                                                           sienna_cichlid_throttler_map);
index 3d188616ba24ceb788a344932aeb2ac13106a779..0fb6be11a0cc7a611ed4275b37740cf04934cbff 100644 (file)
@@ -332,10 +332,13 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu)
                table_context->power_play_table;
        struct smu_baco_context *smu_baco = &smu->smu_baco;
        PPTable_t *pptable = smu->smu_table.driver_pptable;
+#if 0
+       PPTable_t *pptable = smu->smu_table.driver_pptable;
        const OverDriveLimits_t * const overdrive_upperlimits =
                                &pptable->SkuTable.OverDriveLimitsBasicMax;
        const OverDriveLimits_t * const overdrive_lowerlimits =
                                &pptable->SkuTable.OverDriveLimitsMin;
+#endif
 
        if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC)
                smu->dc_controlled_by_gpio = true;
@@ -347,18 +350,30 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu)
        if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
                smu_baco->maco_support = true;
 
+       /*
+        * We are in the transition to a new OD mechanism.
+        * Disable the OD feature support for SMU13 temporarily.
+        * TODO: get this reverted when new OD mechanism online
+        */
+#if 0
        if (!overdrive_lowerlimits->FeatureCtrlMask ||
            !overdrive_upperlimits->FeatureCtrlMask)
                smu->od_enabled = false;
 
-       table_context->thermal_controller_type =
-               powerplay_table->thermal_controller_type;
-
        /*
         * Instead of having its own buffer space and get overdrive_table copied,
         * smu->od_settings just points to the actual overdrive_table
         */
        smu->od_settings = &powerplay_table->overdrive_table;
+#else
+       smu->od_enabled = false;
+#endif
+
+       table_context->thermal_controller_type =
+               powerplay_table->thermal_controller_type;
+
+       smu->adev->pm.no_fan =
+               !(pptable->SkuTable.FeaturesToRun[0] & (1 << FEATURE_FAN_CONTROL_BIT));
 
        return 0;
 }
@@ -1140,7 +1155,6 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
                (OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
        struct smu_13_0_dpm_table *single_dpm_table;
        struct smu_13_0_pcie_table *pcie_table;
-       const int link_width[] = {0, 1, 2, 4, 8, 12, 16};
        uint32_t gen_speed, lane_width;
        int i, curr_freq, size = 0;
        int32_t min_value, max_value;
@@ -1256,7 +1270,7 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
                                        (pcie_table->pcie_lane[i] == 6) ? "x16" : "",
                                        pcie_table->clk_freq[i],
                                        (gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
-                                       (lane_width == DECODE_LANE_WIDTH(link_width[pcie_table->pcie_lane[i]])) ?
+                                       (lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
                                        "*" : "");
                break;
 
index 1ac552142763f8ab2a8f21b9234ded19c6fd3b8b..dc6104a04dce6adbea9f7aa7f69adad875d553b2 100644 (file)
 #define EPSILON 1
 
 #define smnPCIE_ESM_CTRL 0x193D0
-#define smnPCIE_LC_LINK_WIDTH_CNTL 0x1ab40288
+#define smnPCIE_LC_LINK_WIDTH_CNTL 0x1a340288
 #define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L
 #define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x4
+#define MAX_LINK_WIDTH 6
 
 static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COUNT] = {
        MSG_MAP(TestMessage,                         PPSMC_MSG_TestMessage,                     0),
@@ -708,16 +709,19 @@ static int smu_v13_0_6_get_smu_metrics_data(struct smu_context *smu,
                *value = SMUQ10_TO_UINT(metrics->SocketPower) << 8;
                break;
        case METRICS_TEMPERATURE_HOTSPOT:
-               *value = SMUQ10_TO_UINT(metrics->MaxSocketTemperature);
+               *value = SMUQ10_TO_UINT(metrics->MaxSocketTemperature) *
+                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
                break;
        case METRICS_TEMPERATURE_MEM:
-               *value = SMUQ10_TO_UINT(metrics->MaxHbmTemperature);
+               *value = SMUQ10_TO_UINT(metrics->MaxHbmTemperature) *
+                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
                break;
        /* This is the max of all VRs and not just SOC VR.
         * No need to define another data type for the same.
         */
        case METRICS_TEMPERATURE_VRSOC:
-               *value = SMUQ10_TO_UINT(metrics->MaxVrTemperature);
+               *value = SMUQ10_TO_UINT(metrics->MaxVrTemperature) *
+                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
                break;
        default:
                *value = UINT_MAX;
@@ -1966,6 +1970,7 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
        struct amdgpu_device *adev = smu->adev;
        int ret = 0, inst0, xcc0;
        MetricsTable_t *metrics;
+       u16 link_width_level;
 
        inst0 = adev->sdma.instance[0].aid_id;
        xcc0 = GET_INST(GC, 0);
@@ -1993,9 +1998,8 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
 
        gpu_metrics->average_socket_power =
                SMUQ10_TO_UINT(metrics->SocketPower);
-       /* Energy is reported in 15.625mJ units */
-       gpu_metrics->energy_accumulator =
-               SMUQ10_TO_UINT(metrics->SocketEnergyAcc);
+       /* Energy counter reported in 15.259uJ (2^-16) units */
+       gpu_metrics->energy_accumulator = metrics->SocketEnergyAcc;
 
        gpu_metrics->current_gfxclk =
                SMUQ10_TO_UINT(metrics->GfxclkFrequency[xcc0]);
@@ -2017,8 +2021,12 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
        gpu_metrics->throttle_status = 0;
 
        if (!(adev->flags & AMD_IS_APU)) {
+               link_width_level = smu_v13_0_6_get_current_pcie_link_width_level(smu);
+               if (link_width_level > MAX_LINK_WIDTH)
+                       link_width_level = 0;
+
                gpu_metrics->pcie_link_width =
-                       smu_v13_0_6_get_current_pcie_link_width_level(smu);
+                       DECODE_LANE_WIDTH(link_width_level);
                gpu_metrics->pcie_link_speed =
                        smu_v13_0_6_get_current_pcie_link_speed(smu);
        }
index b1f0937ccade8f20b972b11dd177a26ec00278a3..62f2886ab4df6bbff9c84e0422cad4c5414ce51f 100644 (file)
@@ -323,10 +323,12 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
        struct smu_baco_context *smu_baco = &smu->smu_baco;
        PPTable_t *smc_pptable = table_context->driver_pptable;
        BoardTable_t *BoardTable = &smc_pptable->BoardTable;
+#if 0
        const OverDriveLimits_t * const overdrive_upperlimits =
                                &smc_pptable->SkuTable.OverDriveLimitsBasicMax;
        const OverDriveLimits_t * const overdrive_lowerlimits =
                                &smc_pptable->SkuTable.OverDriveLimitsMin;
+#endif
 
        if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
                smu->dc_controlled_by_gpio = true;
@@ -338,18 +340,22 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
        if (smu_baco->platform_support && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
                smu_baco->maco_support = true;
 
+#if 0
        if (!overdrive_lowerlimits->FeatureCtrlMask ||
            !overdrive_upperlimits->FeatureCtrlMask)
                smu->od_enabled = false;
 
-       table_context->thermal_controller_type =
-               powerplay_table->thermal_controller_type;
-
        /*
         * Instead of having its own buffer space and get overdrive_table copied,
         * smu->od_settings just points to the actual overdrive_table
         */
        smu->od_settings = &powerplay_table->overdrive_table;
+#else
+       smu->od_enabled = false;
+#endif
+
+       table_context->thermal_controller_type =
+               powerplay_table->thermal_controller_type;
 
        return 0;
 }
index 504d51c42f798194423e08d43ce35f5df9b77334..aadb396508c5478e0675c0c69f62780296e00722 100644 (file)
@@ -2517,9 +2517,11 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
        };
        int int_status[3], i;
 
-       if (it6505->enable_drv_hold || pm_runtime_get_if_in_use(dev) <= 0)
+       if (it6505->enable_drv_hold || !it6505->powered)
                return IRQ_HANDLED;
 
+       pm_runtime_get_sync(dev);
+
        int_status[0] = it6505_read(it6505, INT_STATUS_01);
        int_status[1] = it6505_read(it6505, INT_STATUS_02);
        int_status[2] = it6505_read(it6505, INT_STATUS_03);
index 5163e5224aad71960f4ec09dad797e0466b89313..9663601ce0981803e0a4e0d3cecba8261097b663 100644 (file)
@@ -774,9 +774,7 @@ static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611,
        dsi->lanes = 4;
        dsi->format = MIPI_DSI_FMT_RGB888;
        dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
-                         MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA |
-                         MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP |
-                         MIPI_DSI_MODE_NO_EOT_PACKET;
+                         MIPI_DSI_MODE_VIDEO_HSE;
 
        ret = devm_mipi_dsi_attach(dev, dsi);
        if (ret < 0) {
index e0dbd9140726b336669db2db854b2556a463ebd1..1f470968ed14b4cec87f59cab03109e6c4beb4ba 100644 (file)
@@ -3456,6 +3456,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
                            connector->base.id, connector->name);
                return NULL;
        }
+       if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
+               drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n",
+                           connector->base.id, connector->name);
+       }
 
        /* it is incorrect if hsync/vsync width is zero */
        if (!hsync_pulse_width || !vsync_pulse_width) {
@@ -3502,27 +3506,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
        if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
                mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
        } else {
-               switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
-               case DRM_EDID_PT_ANALOG_CSYNC:
-               case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC:
-                       drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Analog composite sync!\n",
-                                   connector->base.id, connector->name);
-                       mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC;
-                       break;
-               case DRM_EDID_PT_DIGITAL_CSYNC:
-                       drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Digital composite sync!\n",
-                                   connector->base.id, connector->name);
-                       mode->flags |= DRM_MODE_FLAG_CSYNC;
-                       mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
-                               DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC;
-                       break;
-               case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC:
-                       mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
-                               DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
-                       mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
-                               DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
-                       break;
-               }
+               mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
+                       DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+               mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
+                       DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
        }
 
 set_size:
index 4ea6507a77e5d2edeb65a3b61ae24c2c5eae454a..baaf0e0feb0632e617875395c9c492456f649088 100644 (file)
@@ -623,7 +623,13 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct
        int ret;
 
        if (obj->import_attach) {
+               /* Reset both vm_ops and vm_private_data, so we don't end up with
+                * vm_ops pointing to our implementation if the dma-buf backend
+                * doesn't set those fields.
+                */
                vma->vm_private_data = NULL;
+               vma->vm_ops = NULL;
+
                ret = dma_buf_mmap(obj->dma_buf, vma, 0);
 
                /* Drop the reference drm_gem_mmap_obj() acquired.*/
index f0ee9bcf661dfdad1a59f08759fe64a40d8cccf5..b0c6a2a86f2f39c4ea2b8656bad5c10bfa824e15 100644 (file)
@@ -662,10 +662,24 @@ static const struct intel_display_device_info xe_lpdp_display = {
                BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
 };
 
+/*
+ * Separate detection for no display cases to keep the display id array simple.
+ *
+ * IVB Q requires subvendor and subdevice matching to differentiate from IVB D
+ * GT2 server.
+ */
+static bool has_no_display(struct pci_dev *pdev)
+{
+       static const struct pci_device_id ids[] = {
+               INTEL_IVB_Q_IDS(0),
+               {}
+       };
+
+       return pci_match_id(ids, pdev);
+}
+
 #undef INTEL_VGA_DEVICE
-#undef INTEL_QUANTA_VGA_DEVICE
 #define INTEL_VGA_DEVICE(id, info) { id, info }
-#define INTEL_QUANTA_VGA_DEVICE(info) { 0x16a, info }
 
 static const struct {
        u32 devid;
@@ -690,7 +704,6 @@ static const struct {
        INTEL_IRONLAKE_M_IDS(&ilk_m_display),
        INTEL_SNB_D_IDS(&snb_display),
        INTEL_SNB_M_IDS(&snb_display),
-       INTEL_IVB_Q_IDS(NULL),          /* must be first IVB in list */
        INTEL_IVB_M_IDS(&ivb_display),
        INTEL_IVB_D_IDS(&ivb_display),
        INTEL_HSW_IDS(&hsw_display),
@@ -775,6 +788,11 @@ intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
        if (has_gmdid)
                return probe_gmdid_display(i915, gmdid_ver, gmdid_rel, gmdid_step);
 
+       if (has_no_display(pdev)) {
+               drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
+               return &no_display;
+       }
+
        for (i = 0; i < ARRAY_SIZE(intel_display_ids); i++) {
                if (intel_display_ids[i].devid == pdev->device)
                        return intel_display_ids[i].info;
index 21f92123c844645069311deb630650cccc04b6e0..67e3aaf9b4320cb0d1957cfeeece5c7adf558221 100644 (file)
@@ -2752,7 +2752,7 @@ static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void)
        __drm_atomic_helper_connector_reset(&sdvo_connector->base.base,
                                            &conn_state->base.base);
 
-       INIT_LIST_HEAD(&sdvo_connector->base.panel.fixed_modes);
+       intel_panel_init_alloc(&sdvo_connector->base);
 
        return sdvo_connector;
 }
index 23857cc08eca1fbfec37a6ab0c96987798706a49..2702ad4c26c8858d8703fa1d43ea99720ee5787d 100644 (file)
@@ -165,14 +165,60 @@ static u32 preparser_disable(bool state)
        return MI_ARB_CHECK | 1 << 8 | state;
 }
 
-u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv_reg)
+static i915_reg_t gen12_get_aux_inv_reg(struct intel_engine_cs *engine)
 {
-       u32 gsi_offset = gt->uncore->gsi_offset;
+       switch (engine->id) {
+       case RCS0:
+               return GEN12_CCS_AUX_INV;
+       case BCS0:
+               return GEN12_BCS0_AUX_INV;
+       case VCS0:
+               return GEN12_VD0_AUX_INV;
+       case VCS2:
+               return GEN12_VD2_AUX_INV;
+       case VECS0:
+               return GEN12_VE0_AUX_INV;
+       case CCS0:
+               return GEN12_CCS0_AUX_INV;
+       default:
+               return INVALID_MMIO_REG;
+       }
+}
+
+static bool gen12_needs_ccs_aux_inv(struct intel_engine_cs *engine)
+{
+       i915_reg_t reg = gen12_get_aux_inv_reg(engine);
+
+       if (IS_PONTEVECCHIO(engine->i915))
+               return false;
+
+       /*
+        * So far platforms supported by i915 having flat ccs do not require
+        * AUX invalidation. Check also whether the engine requires it.
+        */
+       return i915_mmio_reg_valid(reg) && !HAS_FLAT_CCS(engine->i915);
+}
+
+u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs)
+{
+       i915_reg_t inv_reg = gen12_get_aux_inv_reg(engine);
+       u32 gsi_offset = engine->gt->uncore->gsi_offset;
+
+       if (!gen12_needs_ccs_aux_inv(engine))
+               return cs;
 
        *cs++ = MI_LOAD_REGISTER_IMM(1) | MI_LRI_MMIO_REMAP_EN;
        *cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset;
        *cs++ = AUX_INV;
-       *cs++ = MI_NOOP;
+
+       *cs++ = MI_SEMAPHORE_WAIT_TOKEN |
+               MI_SEMAPHORE_REGISTER_POLL |
+               MI_SEMAPHORE_POLL |
+               MI_SEMAPHORE_SAD_EQ_SDD;
+       *cs++ = 0;
+       *cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset;
+       *cs++ = 0;
+       *cs++ = 0;
 
        return cs;
 }
@@ -202,8 +248,13 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
 {
        struct intel_engine_cs *engine = rq->engine;
 
-       if (mode & EMIT_FLUSH) {
-               u32 flags = 0;
+       /*
+        * On Aux CCS platforms the invalidation of the Aux
+        * table requires quiescing memory traffic beforehand
+        */
+       if (mode & EMIT_FLUSH || gen12_needs_ccs_aux_inv(engine)) {
+               u32 bit_group_0 = 0;
+               u32 bit_group_1 = 0;
                int err;
                u32 *cs;
 
@@ -211,32 +262,40 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
                if (err)
                        return err;
 
-               flags |= PIPE_CONTROL_TILE_CACHE_FLUSH;
-               flags |= PIPE_CONTROL_FLUSH_L3;
-               flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
-               flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+               bit_group_0 |= PIPE_CONTROL0_HDC_PIPELINE_FLUSH;
+
+               /*
+                * When required, in MTL and beyond platforms we
+                * need to set the CCS_FLUSH bit in the pipe control
+                */
+               if (GRAPHICS_VER_FULL(rq->i915) >= IP_VER(12, 70))
+                       bit_group_0 |= PIPE_CONTROL_CCS_FLUSH;
+
+               bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH;
+               bit_group_1 |= PIPE_CONTROL_FLUSH_L3;
+               bit_group_1 |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+               bit_group_1 |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
                /* Wa_1409600907:tgl,adl-p */
-               flags |= PIPE_CONTROL_DEPTH_STALL;
-               flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
-               flags |= PIPE_CONTROL_FLUSH_ENABLE;
+               bit_group_1 |= PIPE_CONTROL_DEPTH_STALL;
+               bit_group_1 |= PIPE_CONTROL_DC_FLUSH_ENABLE;
+               bit_group_1 |= PIPE_CONTROL_FLUSH_ENABLE;
 
-               flags |= PIPE_CONTROL_STORE_DATA_INDEX;
-               flags |= PIPE_CONTROL_QW_WRITE;
+               bit_group_1 |= PIPE_CONTROL_STORE_DATA_INDEX;
+               bit_group_1 |= PIPE_CONTROL_QW_WRITE;
 
-               flags |= PIPE_CONTROL_CS_STALL;
+               bit_group_1 |= PIPE_CONTROL_CS_STALL;
 
                if (!HAS_3D_PIPELINE(engine->i915))
-                       flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
+                       bit_group_1 &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
                else if (engine->class == COMPUTE_CLASS)
-                       flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
+                       bit_group_1 &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
 
                cs = intel_ring_begin(rq, 6);
                if (IS_ERR(cs))
                        return PTR_ERR(cs);
 
-               cs = gen12_emit_pipe_control(cs,
-                                            PIPE_CONTROL0_HDC_PIPELINE_FLUSH,
-                                            flags, LRC_PPHWSP_SCRATCH_ADDR);
+               cs = gen12_emit_pipe_control(cs, bit_group_0, bit_group_1,
+                                            LRC_PPHWSP_SCRATCH_ADDR);
                intel_ring_advance(rq, cs);
        }
 
@@ -267,10 +326,9 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
                else if (engine->class == COMPUTE_CLASS)
                        flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
 
-               if (!HAS_FLAT_CCS(rq->engine->i915))
-                       count = 8 + 4;
-               else
-                       count = 8;
+               count = 8;
+               if (gen12_needs_ccs_aux_inv(rq->engine))
+                       count += 8;
 
                cs = intel_ring_begin(rq, count);
                if (IS_ERR(cs))
@@ -285,11 +343,7 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
 
                cs = gen8_emit_pipe_control(cs, flags, LRC_PPHWSP_SCRATCH_ADDR);
 
-               if (!HAS_FLAT_CCS(rq->engine->i915)) {
-                       /* hsdes: 1809175790 */
-                       cs = gen12_emit_aux_table_inv(rq->engine->gt,
-                                                     cs, GEN12_GFX_CCS_AUX_NV);
-               }
+               cs = gen12_emit_aux_table_inv(engine, cs);
 
                *cs++ = preparser_disable(false);
                intel_ring_advance(rq, cs);
@@ -300,21 +354,14 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
 
 int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode)
 {
-       intel_engine_mask_t aux_inv = 0;
-       u32 cmd, *cs;
+       u32 cmd = 4;
+       u32 *cs;
 
-       cmd = 4;
        if (mode & EMIT_INVALIDATE) {
                cmd += 2;
 
-               if (!HAS_FLAT_CCS(rq->engine->i915) &&
-                   (rq->engine->class == VIDEO_DECODE_CLASS ||
-                    rq->engine->class == VIDEO_ENHANCEMENT_CLASS)) {
-                       aux_inv = rq->engine->mask &
-                               ~GENMASK(_BCS(I915_MAX_BCS - 1), BCS0);
-                       if (aux_inv)
-                               cmd += 4;
-               }
+               if (gen12_needs_ccs_aux_inv(rq->engine))
+                       cmd += 8;
        }
 
        cs = intel_ring_begin(rq, cmd);
@@ -338,6 +385,10 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode)
                cmd |= MI_INVALIDATE_TLB;
                if (rq->engine->class == VIDEO_DECODE_CLASS)
                        cmd |= MI_INVALIDATE_BSD;
+
+               if (gen12_needs_ccs_aux_inv(rq->engine) &&
+                   rq->engine->class == COPY_ENGINE_CLASS)
+                       cmd |= MI_FLUSH_DW_CCS;
        }
 
        *cs++ = cmd;
@@ -345,14 +396,7 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode)
        *cs++ = 0; /* upper addr */
        *cs++ = 0; /* value */
 
-       if (aux_inv) { /* hsdes: 1809175790 */
-               if (rq->engine->class == VIDEO_DECODE_CLASS)
-                       cs = gen12_emit_aux_table_inv(rq->engine->gt,
-                                                     cs, GEN12_VD0_AUX_NV);
-               else
-                       cs = gen12_emit_aux_table_inv(rq->engine->gt,
-                                                     cs, GEN12_VE0_AUX_NV);
-       }
+       cs = gen12_emit_aux_table_inv(rq->engine, cs);
 
        if (mode & EMIT_INVALIDATE)
                *cs++ = preparser_disable(false);
index 655e5c00ddc27751ef3f92d8020676ca6252d745..867ba697aceb83e5f8c24ca121bf70a7a85b1c62 100644 (file)
@@ -13,6 +13,7 @@
 #include "intel_gt_regs.h"
 #include "intel_gpu_commands.h"
 
+struct intel_engine_cs;
 struct intel_gt;
 struct i915_request;
 
@@ -46,28 +47,32 @@ u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs);
 u32 *gen11_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs);
 u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs);
 
-u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv_reg);
+u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs);
 
 static inline u32 *
-__gen8_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset)
+__gen8_emit_pipe_control(u32 *batch, u32 bit_group_0,
+                        u32 bit_group_1, u32 offset)
 {
        memset(batch, 0, 6 * sizeof(u32));
 
-       batch[0] = GFX_OP_PIPE_CONTROL(6) | flags0;
-       batch[1] = flags1;
+       batch[0] = GFX_OP_PIPE_CONTROL(6) | bit_group_0;
+       batch[1] = bit_group_1;
        batch[2] = offset;
 
        return batch + 6;
 }
 
-static inline u32 *gen8_emit_pipe_control(u32 *batch, u32 flags, u32 offset)
+static inline u32 *gen8_emit_pipe_control(u32 *batch,
+                                         u32 bit_group_1, u32 offset)
 {
-       return __gen8_emit_pipe_control(batch, 0, flags, offset);
+       return __gen8_emit_pipe_control(batch, 0, bit_group_1, offset);
 }
 
-static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset)
+static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 bit_group_0,
+                                          u32 bit_group_1, u32 offset)
 {
-       return __gen8_emit_pipe_control(batch, flags0, flags1, offset);
+       return __gen8_emit_pipe_control(batch, bit_group_0,
+                                       bit_group_1, offset);
 }
 
 static inline u32 *
index 5d143e2a8db03ea60a509a2a7afb649638542720..2bd8d98d211023cb927aa12caa308243ee5fe3cb 100644 (file)
 #define   MI_SEMAPHORE_TARGET(engine)  ((engine)<<15)
 #define MI_SEMAPHORE_WAIT      MI_INSTR(0x1c, 2) /* GEN8+ */
 #define MI_SEMAPHORE_WAIT_TOKEN        MI_INSTR(0x1c, 3) /* GEN12+ */
+#define   MI_SEMAPHORE_REGISTER_POLL   (1 << 16)
 #define   MI_SEMAPHORE_POLL            (1 << 15)
 #define   MI_SEMAPHORE_SAD_GT_SDD      (0 << 12)
 #define   MI_SEMAPHORE_SAD_GTE_SDD     (1 << 12)
 #define   PIPE_CONTROL_QW_WRITE                                (1<<14)
 #define   PIPE_CONTROL_POST_SYNC_OP_MASK                (3<<14)
 #define   PIPE_CONTROL_DEPTH_STALL                     (1<<13)
+#define   PIPE_CONTROL_CCS_FLUSH                       (1<<13) /* MTL+ */
 #define   PIPE_CONTROL_WRITE_FLUSH                     (1<<12)
 #define   PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH       (1<<12) /* gen6+ */
 #define   PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE    (1<<11) /* MBZ on ILK */
index 718cb2c80f79ee2d4c61e2792deeda526d99d64b..2cdfb2f713d02631d4001553f2ac89b828d320ea 100644 (file)
 #define GEN8_PRIVATE_PAT_HI                    _MMIO(0x40e0 + 4)
 #define GEN10_PAT_INDEX(index)                 _MMIO(0x40e0 + (index) * 4)
 #define BSD_HWS_PGA_GEN7                       _MMIO(0x4180)
-#define GEN12_GFX_CCS_AUX_NV                   _MMIO(0x4208)
-#define GEN12_VD0_AUX_NV                       _MMIO(0x4218)
-#define GEN12_VD1_AUX_NV                       _MMIO(0x4228)
+
+#define GEN12_CCS_AUX_INV                      _MMIO(0x4208)
+#define GEN12_VD0_AUX_INV                      _MMIO(0x4218)
+#define GEN12_VE0_AUX_INV                      _MMIO(0x4238)
+#define GEN12_BCS0_AUX_INV                     _MMIO(0x4248)
 
 #define GEN8_RTCR                              _MMIO(0x4260)
 #define GEN8_M1TCR                             _MMIO(0x4264)
 #define GEN8_BTCR                              _MMIO(0x426c)
 #define GEN8_VTCR                              _MMIO(0x4270)
 
-#define GEN12_VD2_AUX_NV                       _MMIO(0x4298)
-#define GEN12_VD3_AUX_NV                       _MMIO(0x42a8)
-#define GEN12_VE0_AUX_NV                       _MMIO(0x4238)
-
 #define BLT_HWS_PGA_GEN7                       _MMIO(0x4280)
 
-#define GEN12_VE1_AUX_NV                       _MMIO(0x42b8)
+#define GEN12_VD2_AUX_INV                      _MMIO(0x4298)
+#define GEN12_CCS0_AUX_INV                     _MMIO(0x42c8)
 #define   AUX_INV                              REG_BIT(0)
+
 #define VEBOX_HWS_PGA_GEN7                     _MMIO(0x4380)
 
 #define GEN12_AUX_ERR_DBG                      _MMIO(0x43f4)
index a4ec20aaafe2850ccf9ed2c7e0973b8bc7fd63c9..9477c24223211cda29d3dcabd78372147063dd3c 100644 (file)
@@ -1364,10 +1364,7 @@ gen12_emit_indirect_ctx_rcs(const struct intel_context *ce, u32 *cs)
            IS_DG2_G11(ce->engine->i915))
                cs = gen8_emit_pipe_control(cs, PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, 0);
 
-       /* hsdes: 1809175790 */
-       if (!HAS_FLAT_CCS(ce->engine->i915))
-               cs = gen12_emit_aux_table_inv(ce->engine->gt,
-                                             cs, GEN12_GFX_CCS_AUX_NV);
+       cs = gen12_emit_aux_table_inv(ce->engine, cs);
 
        /* Wa_16014892111 */
        if (IS_MTL_GRAPHICS_STEP(ce->engine->i915, M, STEP_A0, STEP_B0) ||
@@ -1392,17 +1389,7 @@ gen12_emit_indirect_ctx_xcs(const struct intel_context *ce, u32 *cs)
                                                    PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE,
                                                    0);
 
-       /* hsdes: 1809175790 */
-       if (!HAS_FLAT_CCS(ce->engine->i915)) {
-               if (ce->engine->class == VIDEO_DECODE_CLASS)
-                       cs = gen12_emit_aux_table_inv(ce->engine->gt,
-                                                     cs, GEN12_VD0_AUX_NV);
-               else if (ce->engine->class == VIDEO_ENHANCEMENT_CLASS)
-                       cs = gen12_emit_aux_table_inv(ce->engine->gt,
-                                                     cs, GEN12_VE0_AUX_NV);
-       }
-
-       return cs;
+       return gen12_emit_aux_table_inv(ce->engine, cs);
 }
 
 static void
index ee9f83af7cf68863fb1369367c853b5b832a43c5..477df260ae3ac07949b946c3de40aa6863ae29c3 100644 (file)
@@ -470,12 +470,19 @@ int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val)
        ret = slpc_set_param(slpc,
                             SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY,
                             val);
-       if (ret)
+       if (ret) {
                guc_probe_error(slpc_to_guc(slpc), "Failed to set efficient freq(%d): %pe\n",
                                val, ERR_PTR(ret));
-       else
+       } else {
                slpc->ignore_eff_freq = val;
 
+               /* Set min to RPn when we disable efficient freq */
+               if (val)
+                       ret = slpc_set_param(slpc,
+                                            SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
+                                            slpc->min_freq);
+       }
+
        intel_runtime_pm_put(&i915->runtime_pm, wakeref);
        mutex_unlock(&slpc->lock);
        return ret;
@@ -602,9 +609,8 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc)
                return ret;
 
        if (!slpc->min_freq_softlimit) {
-               ret = intel_guc_slpc_get_min_freq(slpc, &slpc->min_freq_softlimit);
-               if (unlikely(ret))
-                       return ret;
+               /* Min softlimit is initialized to RPn */
+               slpc->min_freq_softlimit = slpc->min_freq;
                slpc_to_gt(slpc)->defaults.min_freq = slpc->min_freq_softlimit;
        } else {
                return intel_guc_slpc_set_min_freq(slpc,
@@ -755,6 +761,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
                return ret;
        }
 
+       /* Set cached value of ignore efficient freq */
+       intel_guc_slpc_set_ignore_eff_freq(slpc, slpc->ignore_eff_freq);
+
        /* Revert SLPC min/max to softlimits if necessary */
        ret = slpc_set_softlimits(slpc);
        if (unlikely(ret)) {
@@ -765,9 +774,6 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
        /* Set cached media freq ratio mode */
        intel_guc_slpc_set_media_ratio_mode(slpc, slpc->media_ratio_mode);
 
-       /* Set cached value of ignore efficient freq */
-       intel_guc_slpc_set_ignore_eff_freq(slpc, slpc->ignore_eff_freq);
-
        return 0;
 }
 
index 2a0438f12a1499b46227066d6fee3f65d3142673..af9afdb53c7f5ada5a79614a2b39911bf387a4ad 100644 (file)
@@ -491,7 +491,7 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
                return;
        }
 
-       msg_length = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, reg);
+       msg_length = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, value);
 
        // check the msg in DATA register.
        msg = vgpu_vreg(vgpu, offset + 4);
index 8ef93889061a6367e3558137a816efa0e32599da..5ec293011d99029f211301d2789272603f7f3dde 100644 (file)
@@ -449,8 +449,11 @@ int i915_active_add_request(struct i915_active *ref, struct i915_request *rq)
                }
        } while (unlikely(is_barrier(active)));
 
-       if (!__i915_active_fence_set(active, fence))
+       fence = __i915_active_fence_set(active, fence);
+       if (!fence)
                __i915_active_acquire(ref);
+       else
+               dma_fence_put(fence);
 
 out:
        i915_active_release(ref);
@@ -469,13 +472,9 @@ __i915_active_set_fence(struct i915_active *ref,
                return NULL;
        }
 
-       rcu_read_lock();
        prev = __i915_active_fence_set(active, fence);
-       if (prev)
-               prev = dma_fence_get_rcu(prev);
-       else
+       if (!prev)
                __i915_active_acquire(ref);
-       rcu_read_unlock();
 
        return prev;
 }
@@ -1019,10 +1018,11 @@ void i915_request_add_active_barriers(struct i915_request *rq)
  *
  * Records the new @fence as the last active fence along its timeline in
  * this active tracker, moving the tracking callbacks from the previous
- * fence onto this one. Returns the previous fence (if not already completed),
- * which the caller must ensure is executed before the new fence. To ensure
- * that the order of fences within the timeline of the i915_active_fence is
- * understood, it should be locked by the caller.
+ * fence onto this one. Gets and returns a reference to the previous fence
+ * (if not already completed), which the caller must put after making sure
+ * that it is executed before the new fence. To ensure that the order of
+ * fences within the timeline of the i915_active_fence is understood, it
+ * should be locked by the caller.
  */
 struct dma_fence *
 __i915_active_fence_set(struct i915_active_fence *active,
@@ -1031,7 +1031,23 @@ __i915_active_fence_set(struct i915_active_fence *active,
        struct dma_fence *prev;
        unsigned long flags;
 
-       if (fence == rcu_access_pointer(active->fence))
+       /*
+        * In case of fences embedded in i915_requests, their memory is
+        * SLAB_FAILSAFE_BY_RCU, then it can be reused right after release
+        * by new requests.  Then, there is a risk of passing back a pointer
+        * to a new, completely unrelated fence that reuses the same memory
+        * while tracked under a different active tracker.  Combined with i915
+        * perf open/close operations that build await dependencies between
+        * engine kernel context requests and user requests from different
+        * timelines, this can lead to dependency loops and infinite waits.
+        *
+        * As a countermeasure, we try to get a reference to the active->fence
+        * first, so if we succeed and pass it back to our user then it is not
+        * released and potentially reused by an unrelated request before the
+        * user has a chance to set up an await dependency on it.
+        */
+       prev = i915_active_fence_get(active);
+       if (fence == prev)
                return fence;
 
        GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags));
@@ -1040,27 +1056,56 @@ __i915_active_fence_set(struct i915_active_fence *active,
         * Consider that we have two threads arriving (A and B), with
         * C already resident as the active->fence.
         *
-        * A does the xchg first, and so it sees C or NULL depending
-        * on the timing of the interrupt handler. If it is NULL, the
-        * previous fence must have been signaled and we know that
-        * we are first on the timeline. If it is still present,
-        * we acquire the lock on that fence and serialise with the interrupt
-        * handler, in the process removing it from any future interrupt
-        * callback. A will then wait on C before executing (if present).
-        *
-        * As B is second, it sees A as the previous fence and so waits for
-        * it to complete its transition and takes over the occupancy for
-        * itself -- remembering that it needs to wait on A before executing.
+        * Both A and B have got a reference to C or NULL, depending on the
+        * timing of the interrupt handler.  Let's assume that if A has got C
+        * then it has locked C first (before B).
         *
         * Note the strong ordering of the timeline also provides consistent
         * nesting rules for the fence->lock; the inner lock is always the
         * older lock.
         */
        spin_lock_irqsave(fence->lock, flags);
-       prev = xchg(__active_fence_slot(active), fence);
-       if (prev) {
-               GEM_BUG_ON(prev == fence);
+       if (prev)
                spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING);
+
+       /*
+        * A does the cmpxchg first, and so it sees C or NULL, as before, or
+        * something else, depending on the timing of other threads and/or
+        * interrupt handler.  If not the same as before then A unlocks C if
+        * applicable and retries, starting from an attempt to get a new
+        * active->fence.  Meanwhile, B follows the same path as A.
+        * Once A succeeds with cmpxch, B fails again, retires, gets A from
+        * active->fence, locks it as soon as A completes, and possibly
+        * succeeds with cmpxchg.
+        */
+       while (cmpxchg(__active_fence_slot(active), prev, fence) != prev) {
+               if (prev) {
+                       spin_unlock(prev->lock);
+                       dma_fence_put(prev);
+               }
+               spin_unlock_irqrestore(fence->lock, flags);
+
+               prev = i915_active_fence_get(active);
+               GEM_BUG_ON(prev == fence);
+
+               spin_lock_irqsave(fence->lock, flags);
+               if (prev)
+                       spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING);
+       }
+
+       /*
+        * If prev is NULL then the previous fence must have been signaled
+        * and we know that we are first on the timeline.  If it is still
+        * present then, having the lock on that fence already acquired, we
+        * serialise with the interrupt handler, in the process of removing it
+        * from any future interrupt callback.  A will then wait on C before
+        * executing (if present).
+        *
+        * As B is second, it sees A as the previous fence and so waits for
+        * it to complete its transition and takes over the occupancy for
+        * itself -- remembering that it needs to wait on A before executing.
+        */
+       if (prev) {
                __list_del_entry(&active->cb.node);
                spin_unlock(prev->lock); /* serialise with prev->cb_list */
        }
@@ -1077,11 +1122,7 @@ int i915_active_fence_set(struct i915_active_fence *active,
        int err = 0;
 
        /* Must maintain timeline ordering wrt previous active requests */
-       rcu_read_lock();
        fence = __i915_active_fence_set(active, &rq->fence);
-       if (fence) /* but the previous fence may not belong to that timeline! */
-               fence = dma_fence_get_rcu(fence);
-       rcu_read_unlock();
        if (fence) {
                err = i915_request_await_dma_fence(rq, fence);
                dma_fence_put(fence);
index 894068bb37b6f1b647c7b7bb55bba08f4a379e47..833b73edefdbb3e9f0f70da3dc9095601bcb92c0 100644 (file)
@@ -1661,6 +1661,11 @@ __i915_request_ensure_parallel_ordering(struct i915_request *rq,
 
        request_to_parent(rq)->parallel.last_rq = i915_request_get(rq);
 
+       /*
+        * Users have to put a reference potentially got by
+        * __i915_active_fence_set() to the returned request
+        * when no longer needed
+        */
        return to_request(__i915_active_fence_set(&timeline->last_request,
                                                  &rq->fence));
 }
@@ -1707,6 +1712,10 @@ __i915_request_ensure_ordering(struct i915_request *rq,
                                                         0);
        }
 
+       /*
+        * Users have to put the reference to prev potentially got
+        * by __i915_active_fence_set() when no longer needed
+        */
        return prev;
 }
 
@@ -1760,6 +1769,8 @@ __i915_request_add_to_timeline(struct i915_request *rq)
                prev = __i915_request_ensure_ordering(rq, timeline);
        else
                prev = __i915_request_ensure_parallel_ordering(rq, timeline);
+       if (prev)
+               i915_request_put(prev);
 
        /*
         * Make sure that no request gazumped us - if it was allocated after
index 5f26090b0c9850a541d563d0648e103a50f72816..89585b31b985e182948d1a3838f21e10b7941ffb 100644 (file)
@@ -310,7 +310,7 @@ static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc)
                dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n",
                         sig_cfg.mode.hactive, new_hactive);
 
-               sig_cfg.mode.hfront_porch = new_hactive - sig_cfg.mode.hactive;
+               sig_cfg.mode.hfront_porch -= new_hactive - sig_cfg.mode.hactive;
                sig_cfg.mode.hactive = new_hactive;
        }
 
index f75c6f09dd2af5fca8431f1144eb3439511f81c0..622f6eb9a8bfd0e70909b684c4b0b4ee0efb0969 100644 (file)
@@ -967,7 +967,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
        /* Determine display colour depth for everything except LVDS now,
         * DP requires this before mode_valid() is called.
         */
-       if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && nv_connector->native_mode)
+       if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS)
                nouveau_connector_detect_depth(connector);
 
        /* Find the native mode if this is a digital panel, if we didn't
@@ -1408,8 +1408,7 @@ nouveau_connector_create(struct drm_device *dev,
                ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index,
                                     &nv_connector->conn);
                if (ret) {
-                       kfree(nv_connector);
-                       return ERR_PTR(ret);
+                       goto drm_conn_err;
                }
 
                ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsHotplug",
@@ -1426,8 +1425,7 @@ nouveau_connector_create(struct drm_device *dev,
                        if (ret) {
                                nvif_event_dtor(&nv_connector->hpd);
                                nvif_conn_dtor(&nv_connector->conn);
-                               kfree(nv_connector);
-                               return ERR_PTR(ret);
+                               goto drm_conn_err;
                        }
                }
        }
@@ -1475,4 +1473,9 @@ nouveau_connector_create(struct drm_device *dev,
 
        drm_connector_register(connector);
        return connector;
+
+drm_conn_err:
+       drm_connector_cleanup(connector);
+       kfree(nv_connector);
+       return ERR_PTR(ret);
 }
index 40c8ea43c42f2bb6888ebbb45fbe4f50eb1d94f5..b8ac66b4a2c4b491e6291b82b7bd383bbd6cbc59 100644 (file)
@@ -26,6 +26,8 @@
 #include "head.h"
 #include "ior.h"
 
+#include <drm/display/drm_dp.h>
+
 #include <subdev/bios.h>
 #include <subdev/bios/init.h>
 #include <subdev/gpio.h>
@@ -634,6 +636,50 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp)
        return outp->dp.rates != 0;
 }
 
+/* XXX: This is a big fat hack, and this is just drm_dp_read_dpcd_caps()
+ * converted to work inside nvkm. This is a temporary holdover until we start
+ * passing the drm_dp_aux device through NVKM
+ */
+static int
+nvkm_dp_read_dpcd_caps(struct nvkm_outp *outp)
+{
+       struct nvkm_i2c_aux *aux = outp->dp.aux;
+       u8 dpcd_ext[DP_RECEIVER_CAP_SIZE];
+       int ret;
+
+       ret = nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, DP_RECEIVER_CAP_SIZE);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Prior to DP1.3 the bit represented by
+        * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved.
+        * If it is set DP_DPCD_REV at 0000h could be at a value less than
+        * the true capability of the panel. The only way to check is to
+        * then compare 0000h and 2200h.
+        */
+       if (!(outp->dp.dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
+             DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT))
+               return 0;
+
+       ret = nvkm_rdaux(aux, DP_DP13_DPCD_REV, dpcd_ext, sizeof(dpcd_ext));
+       if (ret < 0)
+               return ret;
+
+       if (outp->dp.dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) {
+               OUTP_DBG(outp, "Extended DPCD rev less than base DPCD rev (%d > %d)\n",
+                        outp->dp.dpcd[DP_DPCD_REV], dpcd_ext[DP_DPCD_REV]);
+               return 0;
+       }
+
+       if (!memcmp(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext)))
+               return 0;
+
+       memcpy(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext));
+
+       return 0;
+}
+
 void
 nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
 {
@@ -689,7 +735,7 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
                        memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr));
                }
 
-               if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) {
+               if (!nvkm_dp_read_dpcd_caps(outp)) {
                        const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 };
                        const u8 *rate;
                        int rate_max;
index 00dbeda7e3464b3c972d42e1e117887ed1a63f40..de161e7a04aa69f8e1324ec6a16909baa7c3065d 100644 (file)
@@ -117,6 +117,7 @@ void gk104_grctx_generate_r418800(struct gf100_gr *);
 
 extern const struct gf100_grctx_func gk110_grctx;
 void gk110_grctx_generate_r419eb0(struct gf100_gr *);
+void gk110_grctx_generate_r419f78(struct gf100_gr *);
 
 extern const struct gf100_grctx_func gk110b_grctx;
 extern const struct gf100_grctx_func gk208_grctx;
index 94233d0119dff2084d5b09b97be73a4a158f9c00..52a234b1ef010bb5e2b8a7e37fcccaaf43f4e252 100644 (file)
@@ -906,7 +906,9 @@ static void
 gk104_grctx_generate_r419f78(struct gf100_gr *gr)
 {
        struct nvkm_device *device = gr->base.engine.subdev.device;
-       nvkm_mask(device, 0x419f78, 0x00000001, 0x00000000);
+
+       /* bit 3 set disables loads in fp helper invocations, we need it enabled */
+       nvkm_mask(device, 0x419f78, 0x00000009, 0x00000000);
 }
 
 void
index 4391458e1fb2f992597b39f77e53e02dd390667f..3acdd9eeb74a75532c6f5bfeb7f5fdfce7e473b9 100644 (file)
@@ -820,6 +820,15 @@ gk110_grctx_generate_r419eb0(struct gf100_gr *gr)
        nvkm_mask(device, 0x419eb0, 0x00001000, 0x00001000);
 }
 
+void
+gk110_grctx_generate_r419f78(struct gf100_gr *gr)
+{
+       struct nvkm_device *device = gr->base.engine.subdev.device;
+
+       /* bit 3 set disables loads in fp helper invocations, we need it enabled */
+       nvkm_mask(device, 0x419f78, 0x00000008, 0x00000000);
+}
+
 const struct gf100_grctx_func
 gk110_grctx = {
        .main  = gf100_grctx_generate_main,
@@ -854,4 +863,5 @@ gk110_grctx = {
        .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
        .r418800 = gk104_grctx_generate_r418800,
        .r419eb0 = gk110_grctx_generate_r419eb0,
+       .r419f78 = gk110_grctx_generate_r419f78,
 };
index 7b9a34f9ec3c7121528aff09ab69ea8cb8ac5b6a..5597e87624acdd81c7f2ac364a362a35e20c8fa4 100644 (file)
@@ -103,4 +103,5 @@ gk110b_grctx = {
        .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
        .r418800 = gk104_grctx_generate_r418800,
        .r419eb0 = gk110_grctx_generate_r419eb0,
+       .r419f78 = gk110_grctx_generate_r419f78,
 };
index c78d07a8bb7df71aac2cc3450a4b47e2aa661797..612656496541d40d7e89fec024b03139bf4f4c16 100644 (file)
@@ -568,4 +568,5 @@ gk208_grctx = {
        .dist_skip_table = gf117_grctx_generate_dist_skip_table,
        .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
        .r418800 = gk104_grctx_generate_r418800,
+       .r419f78 = gk110_grctx_generate_r419f78,
 };
index beac66eb2a803eb7e3d8a902dfa5703fea6bf2b4..9906974ac3f0772ef759f99ef756249569b594b8 100644 (file)
@@ -988,4 +988,5 @@ gm107_grctx = {
        .r406500 = gm107_grctx_generate_r406500,
        .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
        .r419e00 = gm107_grctx_generate_r419e00,
+       .r419f78 = gk110_grctx_generate_r419f78,
 };
index 3b6c8100a242884f64b0d8b7de86a7daac853776..a7775aa185415a35ac3851237b1cda4aedc835c8 100644 (file)
@@ -206,19 +206,6 @@ tu102_gr_av_to_init_veid(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)
        return gk20a_gr_av_to_init_(blob, 64, 0x00100000, ppack);
 }
 
-int
-tu102_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif)
-{
-       int ret;
-
-       ret = gm200_gr_load(gr, ver, fwif);
-       if (ret)
-               return ret;
-
-       return gk20a_gr_load_net(gr, "gr/", "sw_veid_bundle_init", ver, tu102_gr_av_to_init_veid,
-                                &gr->bundle_veid);
-}
-
 static const struct gf100_gr_fwif
 tu102_gr_fwif[] = {
        {  0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr },
index 8f4f137a2af6b9c26cf56a7d26fb1fed67f9e7cd..213008499caaa182dd8f969a4822f6f025becf13 100644 (file)
@@ -404,38 +404,30 @@ static int jdi_panel_add(struct jdi_panel *jdi)
 
        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(jdi->supplies),
                                      jdi->supplies);
-       if (ret < 0) {
-               dev_err(dev, "failed to init regulator, ret=%d\n", ret);
-               return ret;
-       }
+       if (ret < 0)
+               return dev_err_probe(dev, ret,
+                                    "failed to init regulator, ret=%d\n", ret);
 
        jdi->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
        if (IS_ERR(jdi->enable_gpio)) {
-               ret = PTR_ERR(jdi->enable_gpio);
-               dev_err(dev, "cannot get enable-gpio %d\n", ret);
-               return ret;
+               return dev_err_probe(dev, PTR_ERR(jdi->enable_gpio),
+                                    "cannot get enable-gpio %d\n", ret);
        }
 
        jdi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(jdi->reset_gpio)) {
-               ret = PTR_ERR(jdi->reset_gpio);
-               dev_err(dev, "cannot get reset-gpios %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(jdi->reset_gpio))
+               return dev_err_probe(dev, PTR_ERR(jdi->reset_gpio),
+                                    "cannot get reset-gpios %d\n", ret);
 
        jdi->dcdc_en_gpio = devm_gpiod_get(dev, "dcdc-en", GPIOD_OUT_LOW);
-       if (IS_ERR(jdi->dcdc_en_gpio)) {
-               ret = PTR_ERR(jdi->dcdc_en_gpio);
-               dev_err(dev, "cannot get dcdc-en-gpio %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(jdi->dcdc_en_gpio))
+               return dev_err_probe(dev, PTR_ERR(jdi->dcdc_en_gpio),
+                                    "cannot get dcdc-en-gpio %d\n", ret);
 
        jdi->backlight = drm_panel_create_dsi_backlight(jdi->dsi);
-       if (IS_ERR(jdi->backlight)) {
-               ret = PTR_ERR(jdi->backlight);
-               dev_err(dev, "failed to register backlight %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(jdi->backlight))
+               return dev_err_probe(dev, PTR_ERR(jdi->backlight),
+                                    "failed to register backlight %d\n", ret);
 
        drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs,
                       DRM_MODE_CONNECTOR_DSI);
index 102e1fc7ee383a4ae97cd121e61525ef95ba458d..be4ec5bb5223b855255904b19c1cb898426bbd53 100644 (file)
@@ -569,6 +569,7 @@ static const struct of_device_id s6d7aa0_of_match[] = {
        },
        { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, s6d7aa0_of_match);
 
 static struct mipi_dsi_driver s6d7aa0_driver = {
        .probe = s6d7aa0_probe,
index aaba36b3a674b9cc4cd492ee3196a9e764630798..b38d0e95cd542f7972c4a030a6e83ed1358198ec 100644 (file)
@@ -999,21 +999,21 @@ static const struct panel_desc auo_g104sn02 = {
        .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
-static const struct drm_display_mode auo_g121ean01_mode = {
-       .clock = 66700,
-       .hdisplay = 1280,
-       .hsync_start = 1280 + 58,
-       .hsync_end = 1280 + 58 + 8,
-       .htotal = 1280 + 58 + 8 + 70,
-       .vdisplay = 800,
-       .vsync_start = 800 + 6,
-       .vsync_end = 800 + 6 + 4,
-       .vtotal = 800 + 6 + 4 + 10,
+static const struct display_timing auo_g121ean01_timing = {
+       .pixelclock = { 60000000, 74400000, 90000000 },
+       .hactive = { 1280, 1280, 1280 },
+       .hfront_porch = { 20, 50, 100 },
+       .hback_porch = { 20, 50, 100 },
+       .hsync_len = { 30, 100, 200 },
+       .vactive = { 800, 800, 800 },
+       .vfront_porch = { 2, 10, 25 },
+       .vback_porch = { 2, 10, 25 },
+       .vsync_len = { 4, 18, 50 },
 };
 
 static const struct panel_desc auo_g121ean01 = {
-       .modes = &auo_g121ean01_mode,
-       .num_modes = 1,
+       .timings = &auo_g121ean01_timing,
+       .num_timings = 1,
        .bpc = 8,
        .size = {
                .width = 261,
index ea993d7162e8c90ac53ca6bf17ce4b69c70923ec..307a890fde133c3f2218639c6a385e72d3b49122 100644 (file)
@@ -310,7 +310,7 @@ int qxl_gem_object_create_with_handle(struct qxl_device *qdev,
                                      u32 domain,
                                      size_t size,
                                      struct qxl_surface *surf,
-                                     struct qxl_bo **qobj,
+                                     struct drm_gem_object **gobj,
                                      uint32_t *handle);
 void qxl_gem_object_free(struct drm_gem_object *gobj);
 int qxl_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv);
index d636ba68545134cb41f85f20fe5afbd5cdf2e567..17df5c7ccf69141ad772d184eb05ffbab4ba6133 100644 (file)
@@ -34,6 +34,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
 {
        struct qxl_device *qdev = to_qxl(dev);
        struct qxl_bo *qobj;
+       struct drm_gem_object *gobj;
        uint32_t handle;
        int r;
        struct qxl_surface surf;
@@ -62,11 +63,13 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
 
        r = qxl_gem_object_create_with_handle(qdev, file_priv,
                                              QXL_GEM_DOMAIN_CPU,
-                                             args->size, &surf, &qobj,
+                                             args->size, &surf, &gobj,
                                              &handle);
        if (r)
                return r;
+       qobj = gem_to_qxl_bo(gobj);
        qobj->is_dumb = true;
+       drm_gem_object_put(gobj);
        args->pitch = pitch;
        args->handle = handle;
        return 0;
index a08da0bd9098b68b165745e3bff036a73f228995..fc5e3763c359590a61bd7a82d8e347e92166441d 100644 (file)
@@ -72,32 +72,41 @@ int qxl_gem_object_create(struct qxl_device *qdev, int size,
        return 0;
 }
 
+/*
+ * If the caller passed a valid gobj pointer, it is responsible to call
+ * drm_gem_object_put() when it no longer needs to acess the object.
+ *
+ * If gobj is NULL, it is handled internally.
+ */
 int qxl_gem_object_create_with_handle(struct qxl_device *qdev,
                                      struct drm_file *file_priv,
                                      u32 domain,
                                      size_t size,
                                      struct qxl_surface *surf,
-                                     struct qxl_bo **qobj,
+                                     struct drm_gem_object **gobj,
                                      uint32_t *handle)
 {
-       struct drm_gem_object *gobj;
        int r;
+       struct drm_gem_object *local_gobj;
 
-       BUG_ON(!qobj);
        BUG_ON(!handle);
 
        r = qxl_gem_object_create(qdev, size, 0,
                                  domain,
                                  false, false, surf,
-                                 &gobj);
+                                 &local_gobj);
        if (r)
                return -ENOMEM;
-       r = drm_gem_handle_create(file_priv, gobj, handle);
+       r = drm_gem_handle_create(file_priv, local_gobj, handle);
        if (r)
                return r;
-       /* drop reference from allocate - handle holds it now */
-       *qobj = gem_to_qxl_bo(gobj);
-       drm_gem_object_put(gobj);
+
+       if (gobj)
+               *gobj = local_gobj;
+       else
+               /* drop reference from allocate - handle holds it now */
+               drm_gem_object_put(local_gobj);
+
        return 0;
 }
 
index 30f58b21372aa492462a143924bb667327ce2e34..dd0f834d881ce1b4b48249165e42bb73122d81ce 100644 (file)
@@ -38,7 +38,6 @@ int qxl_alloc_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr
        struct qxl_device *qdev = to_qxl(dev);
        struct drm_qxl_alloc *qxl_alloc = data;
        int ret;
-       struct qxl_bo *qobj;
        uint32_t handle;
        u32 domain = QXL_GEM_DOMAIN_VRAM;
 
@@ -50,7 +49,7 @@ int qxl_alloc_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr
                                                domain,
                                                qxl_alloc->size,
                                                NULL,
-                                               &qobj, &handle);
+                                               NULL, &handle);
        if (ret) {
                DRM_ERROR("%s: failed to create gem ret=%d\n",
                          __func__, ret);
@@ -386,7 +385,6 @@ int qxl_alloc_surf_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
 {
        struct qxl_device *qdev = to_qxl(dev);
        struct drm_qxl_alloc_surf *param = data;
-       struct qxl_bo *qobj;
        int handle;
        int ret;
        int size, actual_stride;
@@ -406,7 +404,7 @@ int qxl_alloc_surf_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
                                                QXL_GEM_DOMAIN_SURFACE,
                                                size,
                                                &surf,
-                                               &qobj, &handle);
+                                               NULL, &handle);
        if (ret) {
                DRM_ERROR("%s: failed to create gem ret=%d\n",
                          __func__, ret);
index a530ecc4d207c66eb621d1065d418a5cd63a9707..bf34498c1b6d769fcae656adcbc68c16a52e9c09 100644 (file)
@@ -833,12 +833,12 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
         * need align with 2 pixel.
         */
        if (fb->format->is_yuv && ((new_plane_state->src.x1 >> 16) % 2)) {
-               DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n");
+               DRM_DEBUG_KMS("Invalid Source: Yuv format not support odd xpos\n");
                return -EINVAL;
        }
 
        if (fb->format->is_yuv && new_plane_state->rotation & DRM_MODE_REFLECT_Y) {
-               DRM_ERROR("Invalid Source: Yuv format does not support this rotation\n");
+               DRM_DEBUG_KMS("Invalid Source: Yuv format does not support this rotation\n");
                return -EINVAL;
        }
 
@@ -846,7 +846,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
                struct vop *vop = to_vop(crtc);
 
                if (!vop->data->afbc) {
-                       DRM_ERROR("vop does not support AFBC\n");
+                       DRM_DEBUG_KMS("vop does not support AFBC\n");
                        return -EINVAL;
                }
 
@@ -855,15 +855,16 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
                        return ret;
 
                if (new_plane_state->src.x1 || new_plane_state->src.y1) {
-                       DRM_ERROR("AFBC does not support offset display, xpos=%d, ypos=%d, offset=%d\n",
-                                 new_plane_state->src.x1,
-                                 new_plane_state->src.y1, fb->offsets[0]);
+                       DRM_DEBUG_KMS("AFBC does not support offset display, " \
+                                     "xpos=%d, ypos=%d, offset=%d\n",
+                                     new_plane_state->src.x1, new_plane_state->src.y1,
+                                     fb->offsets[0]);
                        return -EINVAL;
                }
 
                if (new_plane_state->rotation && new_plane_state->rotation != DRM_MODE_ROTATE_0) {
-                       DRM_ERROR("No rotation support in AFBC, rotation=%d\n",
-                                 new_plane_state->rotation);
+                       DRM_DEBUG_KMS("No rotation support in AFBC, rotation=%d\n",
+                                     new_plane_state->rotation);
                        return -EINVAL;
                }
        }
index 7139a522b2f3bd0774e3a497ada097f7467fae9a..54e3083076b786583064b5f6628ac7fa74e965b0 100644 (file)
@@ -519,7 +519,8 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo,
 
        if (bo->pin_count) {
                *locked = false;
-               *busy = false;
+               if (busy)
+                       *busy = false;
                return false;
        }
 
index 5978e9dbc286fbbc17ed15e3a0c5e395c4925c9e..ebf15f31d97e3018475416121d21ec1c923c27f3 100644 (file)
@@ -209,8 +209,7 @@ int vmbus_connect(void)
         * Setup the vmbus event connection for channel interrupt
         * abstraction stuff
         */
-       vmbus_connection.int_page =
-       (void *)hv_alloc_hyperv_zeroed_page();
+       vmbus_connection.int_page = hv_alloc_hyperv_zeroed_page();
        if (vmbus_connection.int_page == NULL) {
                ret = -ENOMEM;
                goto cleanup;
@@ -225,8 +224,8 @@ int vmbus_connect(void)
         * Setup the monitor notification facility. The 1st page for
         * parent->child and the 2nd page for child->parent
         */
-       vmbus_connection.monitor_pages[0] = (void *)hv_alloc_hyperv_page();
-       vmbus_connection.monitor_pages[1] = (void *)hv_alloc_hyperv_page();
+       vmbus_connection.monitor_pages[0] = hv_alloc_hyperv_page();
+       vmbus_connection.monitor_pages[1] = hv_alloc_hyperv_page();
        if ((vmbus_connection.monitor_pages[0] == NULL) ||
            (vmbus_connection.monitor_pages[1] == NULL)) {
                ret = -ENOMEM;
@@ -333,15 +332,15 @@ void vmbus_disconnect(void)
                destroy_workqueue(vmbus_connection.work_queue);
 
        if (vmbus_connection.int_page) {
-               hv_free_hyperv_page((unsigned long)vmbus_connection.int_page);
+               hv_free_hyperv_page(vmbus_connection.int_page);
                vmbus_connection.int_page = NULL;
        }
 
        set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1);
        set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1);
 
-       hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[0]);
-       hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[1]);
+       hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
+       hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
        vmbus_connection.monitor_pages[0] = NULL;
        vmbus_connection.monitor_pages[1] = NULL;
 }
index dffcc894f1173312951c31c93b67c9002901a9e4..0d7a3ba66396491fb68f94d68fad4780940b7511 100644 (file)
@@ -1628,7 +1628,7 @@ static int hv_free_page_report(struct page_reporting_dev_info *pr_dev_info,
        WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES);
        WARN_ON_ONCE(sgl->length < (HV_HYP_PAGE_SIZE << page_reporting_order));
        local_irq_save(flags);
-       hint = *(struct hv_memory_hint **)this_cpu_ptr(hyperv_pcpu_input_arg);
+       hint = *this_cpu_ptr(hyperv_pcpu_input_arg);
        if (!hint) {
                local_irq_restore(flags);
                return -ENOSPC;
index 542a1d53b303e295f026a46d7cd2bab7ee4e206d..6a2258fef1fe90acc68842ddad6efdd8c2d7621a 100644 (file)
@@ -115,12 +115,12 @@ void *hv_alloc_hyperv_zeroed_page(void)
 }
 EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page);
 
-void hv_free_hyperv_page(unsigned long addr)
+void hv_free_hyperv_page(void *addr)
 {
        if (PAGE_SIZE == HV_HYP_PAGE_SIZE)
-               free_page(addr);
+               free_page((unsigned long)addr);
        else
-               kfree((void *)addr);
+               kfree(addr);
 }
 EXPORT_SYMBOL_GPL(hv_free_hyperv_page);
 
@@ -253,7 +253,7 @@ static void hv_kmsg_dump_unregister(void)
        atomic_notifier_chain_unregister(&panic_notifier_list,
                                         &hyperv_panic_report_block);
 
-       hv_free_hyperv_page((unsigned long)hv_panic_page);
+       hv_free_hyperv_page(hv_panic_page);
        hv_panic_page = NULL;
 }
 
@@ -270,7 +270,7 @@ static void hv_kmsg_dump_register(void)
        ret = kmsg_dump_register(&hv_kmsg_dumper);
        if (ret) {
                pr_err("Hyper-V: kmsg dump register error 0x%x\n", ret);
-               hv_free_hyperv_page((unsigned long)hv_panic_page);
+               hv_free_hyperv_page(hv_panic_page);
                hv_panic_page = NULL;
        }
 }
index a997dbcb563fe86414fd4d9c12b9ec0d952a9342..023807859be721af075c5a786be9c49d9c79da67 100644 (file)
 
 #include <linux/crc16.h>
 #include <linux/debugfs.h>
+#include <linux/delay.h>
 #include <linux/hid.h>
 #include <linux/hwmon.h>
 #include <linux/jiffies.h>
+#include <linux/ktime.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/seq_file.h>
@@ -63,6 +65,8 @@ static const char *const aqc_device_names[] = {
 #define CTRL_REPORT_ID                 0x03
 #define AQUAERO_CTRL_REPORT_ID         0x0b
 
+#define CTRL_REPORT_DELAY              200     /* ms */
+
 /* The HID report that the official software always sends
  * after writing values, currently same for all devices
  */
@@ -527,6 +531,9 @@ struct aqc_data {
        int secondary_ctrl_report_size;
        u8 *secondary_ctrl_report;
 
+       ktime_t last_ctrl_report_op;
+       int ctrl_report_delay;  /* Delay between two ctrl report operations, in ms */
+
        int buffer_size;
        u8 *buffer;
        int checksum_start;
@@ -611,17 +618,35 @@ static int aqc_aquastreamxt_convert_fan_rpm(u16 val)
        return 0;
 }
 
+static void aqc_delay_ctrl_report(struct aqc_data *priv)
+{
+       /*
+        * If previous read or write is too close to this one, delay the current operation
+        * to give the device enough time to process the previous one.
+        */
+       if (priv->ctrl_report_delay) {
+               s64 delta = ktime_ms_delta(ktime_get(), priv->last_ctrl_report_op);
+
+               if (delta < priv->ctrl_report_delay)
+                       msleep(priv->ctrl_report_delay - delta);
+       }
+}
+
 /* Expects the mutex to be locked */
 static int aqc_get_ctrl_data(struct aqc_data *priv)
 {
        int ret;
 
+       aqc_delay_ctrl_report(priv);
+
        memset(priv->buffer, 0x00, priv->buffer_size);
        ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
                                 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
        if (ret < 0)
                ret = -ENODATA;
 
+       priv->last_ctrl_report_op = ktime_get();
+
        return ret;
 }
 
@@ -631,6 +656,8 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
        int ret;
        u16 checksum;
 
+       aqc_delay_ctrl_report(priv);
+
        /* Checksum is not needed for Aquaero */
        if (priv->kind != aquaero) {
                /* Init and xorout value for CRC-16/USB is 0xffff */
@@ -646,12 +673,16 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
        ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
                                 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
        if (ret < 0)
-               return ret;
+               goto record_access_and_ret;
 
        /* The official software sends this report after every change, so do it here as well */
        ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id,
                                 priv->secondary_ctrl_report, priv->secondary_ctrl_report_size,
                                 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+
+record_access_and_ret:
+       priv->last_ctrl_report_op = ktime_get();
+
        return ret;
 }
 
@@ -1524,6 +1555,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
                priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE;
                priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET;
+               priv->ctrl_report_delay = CTRL_REPORT_DELAY;
 
                priv->temp_label = label_temp_sensors;
                priv->virtual_temp_label = label_virtual_temp_sensors;
@@ -1547,6 +1579,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
                priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;
 
                priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
+               priv->ctrl_report_delay = CTRL_REPORT_DELAY;
 
                priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
 
@@ -1597,6 +1630,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
                priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;
 
                priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
+               priv->ctrl_report_delay = CTRL_REPORT_DELAY;
 
                priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
 
@@ -1624,6 +1658,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
                priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;
 
                priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
+               priv->ctrl_report_delay = CTRL_REPORT_DELAY;
 
                priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
                priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
index fa5070ae26bc43d4a362493c2c6a8bacce2284c3..7c5f4b10a7c14ec3a8166be883d0a8a7f05ac8eb 100644 (file)
 enum chips {pfe1100, pfe3000};
 
 /*
- * Disable status check for pfe3000 devices, because some devices report
- * communication error (invalid command) for VOUT_MODE command (0x20)
- * although correct VOUT_MODE (0x16) is returned: it leads to incorrect
- * exponent in linear mode.
+ * Disable status check because some devices report communication error
+ * (invalid command) for VOUT_MODE command (0x20) although the correct
+ * VOUT_MODE (0x16) is returned: it leads to incorrect exponent in linear
+ * mode.
+ * This affects both pfe3000 and pfe1100.
  */
-static struct pmbus_platform_data pfe3000_plat_data = {
+static struct pmbus_platform_data pfe_plat_data = {
        .flags = PMBUS_SKIP_STATUS_CHECK,
 };
 
@@ -94,16 +95,15 @@ static int pfe_pmbus_probe(struct i2c_client *client)
        int model;
 
        model = (int)i2c_match_id(pfe_device_id, client)->driver_data;
+       client->dev.platform_data = &pfe_plat_data;
 
        /*
         * PFE3000-12-069RA devices may not stay in page 0 during device
         * probe which leads to probe failure (read status word failed).
         * So let's set the device to page 0 at the beginning.
         */
-       if (model == pfe3000) {
-               client->dev.platform_data = &pfe3000_plat_data;
+       if (model == pfe3000)
                i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
-       }
 
        return pmbus_do_probe(client, &pfe_driver_info[model]);
 }
index 2d8342fdc25de6bb330233414e54130e2e9f67b8..05c80680dff47a125fc6b495e59131c198c49a76 100644 (file)
@@ -233,13 +233,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
                                   u32 offset)
 {
        u32 val;
+       unsigned long flags;
 
        if (iproc_i2c->idm_base) {
-               spin_lock(&iproc_i2c->idm_lock);
+               spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
                writel(iproc_i2c->ape_addr_mask,
                       iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
                val = readl(iproc_i2c->base + offset);
-               spin_unlock(&iproc_i2c->idm_lock);
+               spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
        } else {
                val = readl(iproc_i2c->base + offset);
        }
@@ -250,12 +251,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
 static inline void iproc_i2c_wr_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
                                    u32 offset, u32 val)
 {
+       unsigned long flags;
+
        if (iproc_i2c->idm_base) {
-               spin_lock(&iproc_i2c->idm_lock);
+               spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
                writel(iproc_i2c->ape_addr_mask,
                       iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
                writel(val, iproc_i2c->base + offset);
-               spin_unlock(&iproc_i2c->idm_lock);
+               spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
        } else {
                writel(val, iproc_i2c->base + offset);
        }
index 3bfd7a2232dbd0bb2fe2dfdfe0bece21c15c82a2..24bef0025c988b16213b2a34ce5cfe9b93a8f140 100644 (file)
@@ -588,9 +588,21 @@ i2c_dw_read(struct dw_i2c_dev *dev)
                        u32 flags = msgs[dev->msg_read_idx].flags;
 
                        regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
+                       tmp &= DW_IC_DATA_CMD_DAT;
                        /* Ensure length byte is a valid value */
-                       if (flags & I2C_M_RECV_LEN &&
-                           (tmp & DW_IC_DATA_CMD_DAT) <= I2C_SMBUS_BLOCK_MAX && tmp > 0) {
+                       if (flags & I2C_M_RECV_LEN) {
+                               /*
+                                * if IC_EMPTYFIFO_HOLD_MASTER_EN is set, which cannot be
+                                * detected from the registers, the controller can be
+                                * disabled if the STOP bit is set. But it is only set
+                                * after receiving block data response length in
+                                * I2C_FUNC_SMBUS_BLOCK_DATA case. That needs to read
+                                * another byte with STOP bit set when the block data
+                                * response length is invalid to complete the transaction.
+                                */
+                               if (!tmp || tmp > I2C_SMBUS_BLOCK_MAX)
+                                       tmp = 1;
+
                                len = i2c_dw_recv_len(dev, tmp);
                        }
                        *buf++ = tmp;
index e067671b3ce2eebed4eab2cb51301aaaa3890529..0980c773cb5b1aa790b8ed39a8132bdccc892ac7 100644 (file)
@@ -330,6 +330,14 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context)
        struct hisi_i2c_controller *ctlr = context;
        u32 int_stat;
 
+       /*
+        * Don't handle the interrupt if cltr->completion is NULL. We may
+        * reach here because the interrupt is spurious or the transfer is
+        * started by another port (e.g. firmware) rather than us.
+        */
+       if (!ctlr->completion)
+               return IRQ_NONE;
+
        int_stat = readl(ctlr->iobase + HISI_I2C_INT_MSTAT);
        hisi_i2c_clear_int(ctlr, int_stat);
        if (!(int_stat & HISI_I2C_INT_ALL))
index c3287c887c6fa78428ccc2f2bd0f855632da5da2..150d923ca7f1436b18200cefa528b9c123a89c65 100644 (file)
@@ -209,6 +209,9 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
        lpi2c_imx_set_mode(lpi2c_imx);
 
        clk_rate = clk_get_rate(lpi2c_imx->clks[0].clk);
+       if (!clk_rate)
+               return -EINVAL;
+
        if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
                filt = 0;
        else
index ad8270cdbd3ebe82df9ba319593b0a694f5421c0..fa6020dced595d863c61b3626f2cd02bba417f6c 100644 (file)
@@ -250,7 +250,8 @@ static int p2wi_probe(struct platform_device *pdev)
 
        p2wi->rstc = devm_reset_control_get_exclusive(dev, NULL);
        if (IS_ERR(p2wi->rstc)) {
-               dev_err(dev, "failed to retrieve reset controller: %d\n", ret);
+               dev_err(dev, "failed to retrieve reset controller: %pe\n",
+                       p2wi->rstc);
                return PTR_ERR(p2wi->rstc);
        }
 
index bcbbf23aa530c946749464abe0af4385e920df31..03fc10b45bd6e9af5a2981b431250116d828b34d 100644 (file)
@@ -442,7 +442,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
        if (IS_VI(i2c_dev))
                return 0;
 
-       if (!i2c_dev->hw->has_apb_dma) {
+       if (i2c_dev->hw->has_apb_dma) {
                if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) {
                        dev_dbg(i2c_dev->dev, "APB DMA support not enabled\n");
                        return 0;
@@ -460,6 +460,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
        i2c_dev->dma_chan = dma_request_chan(i2c_dev->dev, "tx");
        if (IS_ERR(i2c_dev->dma_chan)) {
                err = PTR_ERR(i2c_dev->dma_chan);
+               i2c_dev->dma_chan = NULL;
                goto err_out;
        }
 
index 8685e0b58a83854ce64c6fe6b38b82c519064223..7bc3ebfe8081b404d5ad56791f562b7f15531f3d 100644 (file)
@@ -62,7 +62,6 @@
 #define AD7192_MODE_STA_MASK   BIT(20) /* Status Register transmission Mask */
 #define AD7192_MODE_CLKSRC(x)  (((x) & 0x3) << 18) /* Clock Source Select */
 #define AD7192_MODE_SINC3      BIT(15) /* SINC3 Filter Select */
-#define AD7192_MODE_ACX                BIT(14) /* AC excitation enable(AD7195 only)*/
 #define AD7192_MODE_ENPAR      BIT(13) /* Parity Enable */
 #define AD7192_MODE_CLKDIV     BIT(12) /* Clock divide by 2 (AD7190/2 only)*/
 #define AD7192_MODE_SCYCLE     BIT(11) /* Single cycle conversion */
@@ -91,6 +90,7 @@
 /* Configuration Register Bit Designations (AD7192_REG_CONF) */
 
 #define AD7192_CONF_CHOP       BIT(23) /* CHOP enable */
+#define AD7192_CONF_ACX                BIT(22) /* AC excitation enable(AD7195 only) */
 #define AD7192_CONF_REFSEL     BIT(20) /* REFIN1/REFIN2 Reference Select */
 #define AD7192_CONF_CHAN(x)    ((x) << 8) /* Channel select */
 #define AD7192_CONF_CHAN_MASK  (0x7FF << 8) /* Channel select mask */
@@ -472,7 +472,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev,
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ad7192_state *st = iio_priv(indio_dev);
 
-       return sysfs_emit(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX));
+       return sysfs_emit(buf, "%d\n", !!(st->conf & AD7192_CONF_ACX));
 }
 
 static ssize_t ad7192_show_bridge_switch(struct device *dev,
@@ -513,13 +513,13 @@ static ssize_t ad7192_set(struct device *dev,
 
                ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon);
                break;
-       case AD7192_REG_MODE:
+       case AD7192_REG_CONF:
                if (val)
-                       st->mode |= AD7192_MODE_ACX;
+                       st->conf |= AD7192_CONF_ACX;
                else
-                       st->mode &= ~AD7192_MODE_ACX;
+                       st->conf &= ~AD7192_CONF_ACX;
 
-               ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
+               ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
                break;
        default:
                ret = -EINVAL;
@@ -579,12 +579,11 @@ static IIO_DEVICE_ATTR(bridge_switch_en, 0644,
 
 static IIO_DEVICE_ATTR(ac_excitation_en, 0644,
                       ad7192_show_ac_excitation, ad7192_set,
-                      AD7192_REG_MODE);
+                      AD7192_REG_CONF);
 
 static struct attribute *ad7192_attributes[] = {
        &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
        &iio_dev_attr_bridge_switch_en.dev_attr.attr,
-       &iio_dev_attr_ac_excitation_en.dev_attr.attr,
        NULL
 };
 
@@ -595,6 +594,7 @@ static const struct attribute_group ad7192_attribute_group = {
 static struct attribute *ad7195_attributes[] = {
        &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
        &iio_dev_attr_bridge_switch_en.dev_attr.attr,
+       &iio_dev_attr_ac_excitation_en.dev_attr.attr,
        NULL
 };
 
index 213526c1592f1c1f3f168b2a68fc4f9b0e86cd2f..aea83f369437428dd53eef331d0fbf7c6570dcd3 100644 (file)
@@ -124,6 +124,7 @@ static const struct regmap_config ina2xx_regmap_config = {
 enum ina2xx_ids { ina219, ina226 };
 
 struct ina2xx_config {
+       const char *name;
        u16 config_default;
        int calibration_value;
        int shunt_voltage_lsb;  /* nV */
@@ -155,6 +156,7 @@ struct ina2xx_chip_info {
 
 static const struct ina2xx_config ina2xx_config[] = {
        [ina219] = {
+               .name = "ina219",
                .config_default = INA219_CONFIG_DEFAULT,
                .calibration_value = 4096,
                .shunt_voltage_lsb = 10000,
@@ -164,6 +166,7 @@ static const struct ina2xx_config ina2xx_config[] = {
                .chip_id = ina219,
        },
        [ina226] = {
+               .name = "ina226",
                .config_default = INA226_CONFIG_DEFAULT,
                .calibration_value = 2048,
                .shunt_voltage_lsb = 2500,
@@ -996,7 +999,7 @@ static int ina2xx_probe(struct i2c_client *client)
        /* Patch the current config register with default. */
        val = chip->config->config_default;
 
-       if (id->driver_data == ina226) {
+       if (type == ina226) {
                ina226_set_average(chip, INA226_DEFAULT_AVG, &val);
                ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val);
                ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val);
@@ -1015,7 +1018,7 @@ static int ina2xx_probe(struct i2c_client *client)
        }
 
        indio_dev->modes = INDIO_DIRECT_MODE;
-       if (id->driver_data == ina226) {
+       if (type == ina226) {
                indio_dev->channels = ina226_channels;
                indio_dev->num_channels = ARRAY_SIZE(ina226_channels);
                indio_dev->info = &ina226_info;
@@ -1024,7 +1027,7 @@ static int ina2xx_probe(struct i2c_client *client)
                indio_dev->num_channels = ARRAY_SIZE(ina219_channels);
                indio_dev->info = &ina219_info;
        }
-       indio_dev->name = id->name;
+       indio_dev->name = id ? id->name : chip->config->name;
 
        ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev,
                                          &ina2xx_setup_ops);
index af6bfcc190752e9b674a5294004dcd6a35b51dd0..eb78a6f17fd07c1f40bbf87b66bff245a816a3ae 100644 (file)
@@ -916,12 +916,6 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
                goto err_vref;
        }
 
-       ret = clk_prepare_enable(priv->core_clk);
-       if (ret) {
-               dev_err(dev, "failed to enable core clk\n");
-               goto err_core_clk;
-       }
-
        regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
        regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
                           MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
@@ -948,8 +942,6 @@ err_adc_clk:
        regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
                           MESON_SAR_ADC_REG3_ADC_EN, 0);
        meson_sar_adc_set_bandgap(indio_dev, false);
-       clk_disable_unprepare(priv->core_clk);
-err_core_clk:
        regulator_disable(priv->vref);
 err_vref:
        meson_sar_adc_unlock(indio_dev);
@@ -977,8 +969,6 @@ static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
 
        meson_sar_adc_set_bandgap(indio_dev, false);
 
-       clk_disable_unprepare(priv->core_clk);
-
        regulator_disable(priv->vref);
 
        if (!ret)
@@ -1211,7 +1201,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
        if (IS_ERR(priv->clkin))
                return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n");
 
-       priv->core_clk = devm_clk_get(dev, "core");
+       priv->core_clk = devm_clk_get_enabled(dev, "core");
        if (IS_ERR(priv->core_clk))
                return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n");
 
@@ -1294,15 +1284,26 @@ static int meson_sar_adc_remove(struct platform_device *pdev)
 static int meson_sar_adc_suspend(struct device *dev)
 {
        struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
 
        meson_sar_adc_hw_disable(indio_dev);
 
+       clk_disable_unprepare(priv->core_clk);
+
        return 0;
 }
 
 static int meson_sar_adc_resume(struct device *dev)
 {
        struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+       int ret;
+
+       ret = clk_prepare_enable(priv->core_clk);
+       if (ret) {
+               dev_err(dev, "failed to enable core clk\n");
+               return ret;
+       }
 
        return meson_sar_adc_hw_enable(indio_dev);
 }
index 943e9e14d1e99259d87b2daefcd5d56be12bc700..b72d39fc2434e44071cae83ae9b33e027c40eae1 100644 (file)
@@ -253,7 +253,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
        platform_set_drvdata(pdev, indio_dev);
 
        state->ec = ec->ec_dev;
-       state->msg = devm_kzalloc(&pdev->dev,
+       state->msg = devm_kzalloc(&pdev->dev, sizeof(*state->msg) +
                                max((u16)sizeof(struct ec_params_motion_sense),
                                state->ec->max_response), GFP_KERNEL);
        if (!state->msg)
index 9bf8337806fcf1c686ab4106e63fabc26ec6dc5f..8c8e0bbfc99f2c9e6683eed9b28bf96d974c2be3 100644 (file)
@@ -344,9 +344,12 @@ static int admv1013_update_quad_filters(struct admv1013_state *st)
 
 static int admv1013_update_mixer_vgate(struct admv1013_state *st)
 {
-       unsigned int vcm, mixer_vgate;
+       unsigned int mixer_vgate;
+       int vcm;
 
        vcm = regulator_get_voltage(st->reg);
+       if (vcm < 0)
+               return vcm;
 
        if (vcm < 1800000)
                mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100;
index 6a18b363cf73ba5e547fa8a7b303494ceab3821d..b6e6b1df8a618995e23eeca4ad89f4776091bada 100644 (file)
@@ -2687,7 +2687,7 @@ unknown_format:
 static int lsm6dsx_get_acpi_mount_matrix(struct device *dev,
                                          struct iio_mount_matrix *orientation)
 {
-       return false;
+       return -EOPNOTSUPP;
 }
 
 #endif
index c117f50d0cf3745be51303d806d946b074e4407a..adcba832e6fa1b55a3d1026f690d4a699a638465 100644 (file)
@@ -1888,7 +1888,7 @@ static const struct iio_buffer_setup_ops noop_ring_setup_ops;
 int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
 {
        struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
-       struct fwnode_handle *fwnode;
+       struct fwnode_handle *fwnode = NULL;
        int ret;
 
        if (!indio_dev->info)
@@ -1899,7 +1899,8 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
        /* If the calling driver did not initialize firmware node, do it here */
        if (dev_fwnode(&indio_dev->dev))
                fwnode = dev_fwnode(&indio_dev->dev);
-       else
+       /* The default dummy IIO device has no parent */
+       else if (indio_dev->dev.parent)
                fwnode = dev_fwnode(indio_dev->dev.parent);
        device_set_node(&indio_dev->dev, fwnode);
 
index 489902bed7f0ec3bb4d32adf07d4947f10cb431b..b50bf8973d9ad140ceaa9ffb1377afa4fb3dbe93 100644 (file)
@@ -190,7 +190,7 @@ static const struct iio_itime_sel_mul bu27008_itimes[] = {
        .address = BU27008_REG_##data##_LO,                                     \
        .scan_index = BU27008_##color,                                          \
        .scan_type = {                                                          \
-               .sign = 's',                                                    \
+               .sign = 'u',                                                    \
                .realbits = 16,                                                 \
                .storagebits = 16,                                              \
                .endianness = IIO_LE,                                           \
@@ -633,7 +633,7 @@ static int bu27008_try_find_new_time_gain(struct bu27008_data *data, int val,
        for (i = 0; i < data->gts.num_itime; i++) {
                new_time_sel = data->gts.itime_table[i].sel;
                ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,
-                                       new_time_sel, val, val2 * 1000, gain_sel);
+                                       new_time_sel, val, val2, gain_sel);
                if (!ret)
                        break;
        }
@@ -662,7 +662,7 @@ static int bu27008_set_scale(struct bu27008_data *data,
                goto unlock_out;
 
        ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel,
-                                               val, val2 * 1000, &gain_sel);
+                                               val, val2, &gain_sel);
        if (ret) {
                ret = bu27008_try_find_new_time_gain(data, val, val2, &gain_sel);
                if (ret)
@@ -677,6 +677,21 @@ unlock_out:
        return ret;
 }
 
+static int bu27008_write_raw_get_fmt(struct iio_dev *indio_dev,
+                                    struct iio_chan_spec const *chan,
+                                    long mask)
+{
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               return IIO_VAL_INT_PLUS_NANO;
+       case IIO_CHAN_INFO_INT_TIME:
+               return IIO_VAL_INT_PLUS_MICRO;
+       default:
+               return -EINVAL;
+       }
+}
+
 static int bu27008_write_raw(struct iio_dev *idev,
                             struct iio_chan_spec const *chan,
                             int val, int val2, long mask)
@@ -756,6 +771,7 @@ static int bu27008_update_scan_mode(struct iio_dev *idev,
 static const struct iio_info bu27008_info = {
        .read_raw = &bu27008_read_raw,
        .write_raw = &bu27008_write_raw,
+       .write_raw_get_fmt = &bu27008_write_raw_get_fmt,
        .read_avail = &bu27008_read_avail,
        .update_scan_mode = bu27008_update_scan_mode,
        .validate_trigger = iio_validate_own_trigger,
index e63ef5789cde1e4fd17b4485761b461308007283..bf3de853a811dccaefcba995a2e7151120be5397 100644 (file)
@@ -575,7 +575,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
                return -EINVAL;
 
        if (chan == BU27034_CHAN_ALS) {
-               if (val == 0 && val2 == 1000)
+               if (val == 0 && val2 == 1000000)
                        return 0;
 
                return -EINVAL;
@@ -587,7 +587,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
                goto unlock_out;
 
        ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel,
-                                               val, val2 * 1000, &gain_sel);
+                                               val, val2, &gain_sel);
        if (ret) {
                /*
                 * Could not support scale with given time. Need to change time.
@@ -624,7 +624,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
 
                        /* Can we provide requested scale with this time? */
                        ret = iio_gts_find_gain_sel_for_scale_using_time(
-                               &data->gts, new_time_sel, val, val2 * 1000,
+                               &data->gts, new_time_sel, val, val2,
                                &gain_sel);
                        if (ret)
                                continue;
@@ -1217,6 +1217,21 @@ static int bu27034_read_raw(struct iio_dev *idev,
        }
 }
 
+static int bu27034_write_raw_get_fmt(struct iio_dev *indio_dev,
+                                    struct iio_chan_spec const *chan,
+                                    long mask)
+{
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               return IIO_VAL_INT_PLUS_NANO;
+       case IIO_CHAN_INFO_INT_TIME:
+               return IIO_VAL_INT_PLUS_MICRO;
+       default:
+               return -EINVAL;
+       }
+}
+
 static int bu27034_write_raw(struct iio_dev *idev,
                             struct iio_chan_spec const *chan,
                             int val, int val2, long mask)
@@ -1267,6 +1282,7 @@ static int bu27034_read_avail(struct iio_dev *idev,
 static const struct iio_info bu27034_info = {
        .read_raw = &bu27034_read_raw,
        .write_raw = &bu27034_write_raw,
+       .write_raw_get_fmt = &bu27034_write_raw_get_fmt,
        .read_avail = &bu27034_read_avail,
 };
 
index 755a9c57db6f3a7e8809a5fd75b9a5182ee3a064..f9ab671c8eda556f6ac9aa72ae787392beb72edd 100644 (file)
@@ -85,6 +85,8 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
        dma_addr_t mask;
        int i;
 
+       umem->iova = va = virt;
+
        if (umem->is_odp) {
                unsigned int page_size = BIT(to_ib_umem_odp(umem)->page_shift);
 
@@ -100,7 +102,6 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
         */
        pgsz_bitmap &= GENMASK(BITS_PER_LONG - 1, PAGE_SHIFT);
 
-       umem->iova = va = virt;
        /* The best result is the smallest page size that results in the minimum
         * number of required pages. Compute the largest page size that could
         * work based on VA address bits that don't change.
index b42166fe7454045c87a442d62695129ec7e83b7a..63e98e2d3596297bfcd16e206c853a1df4875bd8 100644 (file)
@@ -1253,6 +1253,8 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
 
        rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode);
        if (rc) {
+               bnxt_unregister_dev(rdev->en_dev);
+               clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
                ibdev_err(&rdev->ibdev, "Failed to get chip context\n");
                return -EINVAL;
        }
@@ -1526,8 +1528,8 @@ static void bnxt_re_remove(struct auxiliary_device *adev)
        }
        bnxt_re_setup_cc(rdev, false);
        ib_unregister_device(&rdev->ibdev);
-       ib_dealloc_device(&rdev->ibdev);
        bnxt_re_dev_uninit(rdev);
+       ib_dealloc_device(&rdev->ibdev);
 skip_remove:
        mutex_unlock(&bnxt_re_mutex);
 }
index 5fd8f7c90bb06a8b734f568c1c24c06a70457282..739d942761d16de6f9e187ddd98b0ced6612d9d6 100644 (file)
@@ -819,6 +819,7 @@ static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res,
        }
 
        memset((u8 *)dpit->tbl, 0xFF, bytes);
+       mutex_init(&res->dpi_tbl_lock);
        dpit->priv_db = dpit->ucreg.bar_reg + dpit->ucreg.offset;
 
        return 0;
index 9dbb89e9f4afc753a0a205ce8d1fed8acb43b258..baaa4406d5e60f464a2f95f5ba23467daa62b25f 100644 (file)
@@ -12307,6 +12307,7 @@ static void free_cntrs(struct hfi1_devdata *dd)
 
        if (dd->synth_stats_timer.function)
                del_timer_sync(&dd->synth_stats_timer);
+       cancel_work_sync(&dd->update_cntr_work);
        ppd = (struct hfi1_pportdata *)(dd + 1);
        for (i = 0; i < dd->num_pports; i++, ppd++) {
                kfree(ppd->cntrs);
index 8f385f9c2dd382e18f3ce17ae2a66b4f83c8e68b..d5f2a6b5376bd47ea0ff822b67c16ec7020ecfd2 100644 (file)
@@ -83,6 +83,11 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm)
 
                temp = agg_peak[bucket] * bcm->vote_scale;
                bcm->vote_y[bucket] = bcm_div(temp, bcm->aux_data.unit);
+
+               if (bcm->enable_mask && (bcm->vote_x[bucket] || bcm->vote_y[bucket])) {
+                       bcm->vote_x[bucket] = 0;
+                       bcm->vote_y[bucket] = bcm->enable_mask;
+               }
        }
 
        if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 &&
index 04391c1ba465c0c8d46f8d8f2bb5f15a56d78af9..7843d8864d6ba75b233233f5e116463c74c3a6bd 100644 (file)
@@ -81,6 +81,7 @@ struct qcom_icc_node {
  * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm
  * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm
  * @vote_scale: scaling factor for vote_x and vote_y
+ * @enable_mask: optional mask to send as vote instead of vote_x/vote_y
  * @dirty: flag used to indicate whether the bcm needs to be committed
  * @keepalive: flag used to indicate whether a keepalive is required
  * @aux_data: auxiliary data used when calculating threshold values and
@@ -97,6 +98,7 @@ struct qcom_icc_bcm {
        u64 vote_x[QCOM_ICC_NUM_BUCKETS];
        u64 vote_y[QCOM_ICC_NUM_BUCKETS];
        u64 vote_scale;
+       u32 enable_mask;
        bool dirty;
        bool keepalive;
        struct bcm_db aux_data;
index da21cc31a580883045920fc2e7d6fde79e80be7e..f56538669de0ecbcabe69c5113f5b1cfd98c03bd 100644 (file)
@@ -1873,6 +1873,7 @@ static struct qcom_icc_node srvc_snoc = {
 
 static struct qcom_icc_bcm bcm_acv = {
        .name = "ACV",
+       .enable_mask = 0x8,
        .num_nodes = 1,
        .nodes = { &ebi },
 };
index 2d7a8e7b85ec29e94684ee7cc172be46109f89ec..e64c214b4020954d52c7de23888a744c3dead255 100644 (file)
@@ -1337,6 +1337,7 @@ static struct qcom_icc_node qns_mem_noc_sf_disp = {
 
 static struct qcom_icc_bcm bcm_acv = {
        .name = "ACV",
+       .enable_mask = 0x8,
        .num_nodes = 1,
        .nodes = { &ebi },
 };
@@ -1349,6 +1350,7 @@ static struct qcom_icc_bcm bcm_ce0 = {
 
 static struct qcom_icc_bcm bcm_cn0 = {
        .name = "CN0",
+       .enable_mask = 0x1,
        .keepalive = true,
        .num_nodes = 55,
        .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie,
@@ -1383,6 +1385,7 @@ static struct qcom_icc_bcm bcm_cn0 = {
 
 static struct qcom_icc_bcm bcm_co0 = {
        .name = "CO0",
+       .enable_mask = 0x1,
        .num_nodes = 2,
        .nodes = { &qxm_nsp, &qns_nsp_gemnoc },
 };
@@ -1403,6 +1406,7 @@ static struct qcom_icc_bcm bcm_mm0 = {
 
 static struct qcom_icc_bcm bcm_mm1 = {
        .name = "MM1",
+       .enable_mask = 0x1,
        .num_nodes = 12,
        .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp,
                   &qnm_camnoc_sf, &qnm_mdp,
@@ -1445,6 +1449,7 @@ static struct qcom_icc_bcm bcm_sh0 = {
 
 static struct qcom_icc_bcm bcm_sh1 = {
        .name = "SH1",
+       .enable_mask = 0x1,
        .num_nodes = 7,
        .nodes = { &alm_gpu_tcu, &alm_sys_tcu,
                   &qnm_nsp_gemnoc, &qnm_pcie,
@@ -1461,6 +1466,7 @@ static struct qcom_icc_bcm bcm_sn0 = {
 
 static struct qcom_icc_bcm bcm_sn1 = {
        .name = "SN1",
+       .enable_mask = 0x1,
        .num_nodes = 4,
        .nodes = { &qhm_gic, &qxm_pimem,
                   &xm_gic, &qns_gemnoc_gc },
@@ -1492,6 +1498,7 @@ static struct qcom_icc_bcm bcm_sn7 = {
 
 static struct qcom_icc_bcm bcm_acv_disp = {
        .name = "ACV",
+       .enable_mask = 0x1,
        .num_nodes = 1,
        .nodes = { &ebi_disp },
 };
@@ -1510,6 +1517,7 @@ static struct qcom_icc_bcm bcm_mm0_disp = {
 
 static struct qcom_icc_bcm bcm_mm1_disp = {
        .name = "MM1",
+       .enable_mask = 0x1,
        .num_nodes = 3,
        .nodes = { &qnm_mdp_disp, &qnm_rot_disp,
                   &qns_mem_noc_sf_disp },
@@ -1523,6 +1531,7 @@ static struct qcom_icc_bcm bcm_sh0_disp = {
 
 static struct qcom_icc_bcm bcm_sh1_disp = {
        .name = "SH1",
+       .enable_mask = 0x1,
        .num_nodes = 1,
        .nodes = { &qnm_pcie_disp },
 };
index d823ba988ef68c75a976de744c0e04750364bc2b..0864ed285375e980c125147723e81641ed47f323 100644 (file)
@@ -1473,6 +1473,7 @@ static struct qcom_icc_node qns_mem_noc_sf_cam_ife_2 = {
 
 static struct qcom_icc_bcm bcm_acv = {
        .name = "ACV",
+       .enable_mask = 0x8,
        .num_nodes = 1,
        .nodes = { &ebi },
 };
@@ -1485,6 +1486,7 @@ static struct qcom_icc_bcm bcm_ce0 = {
 
 static struct qcom_icc_bcm bcm_cn0 = {
        .name = "CN0",
+       .enable_mask = 0x1,
        .keepalive = true,
        .num_nodes = 54,
        .nodes = { &qsm_cfg, &qhs_ahb2phy0,
@@ -1524,6 +1526,7 @@ static struct qcom_icc_bcm bcm_cn1 = {
 
 static struct qcom_icc_bcm bcm_co0 = {
        .name = "CO0",
+       .enable_mask = 0x1,
        .num_nodes = 2,
        .nodes = { &qxm_nsp, &qns_nsp_gemnoc },
 };
@@ -1549,6 +1552,7 @@ static struct qcom_icc_bcm bcm_mm0 = {
 
 static struct qcom_icc_bcm bcm_mm1 = {
        .name = "MM1",
+       .enable_mask = 0x1,
        .num_nodes = 8,
        .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp,
                   &qnm_camnoc_sf, &qnm_vapss_hcp,
@@ -1589,6 +1593,7 @@ static struct qcom_icc_bcm bcm_sh0 = {
 
 static struct qcom_icc_bcm bcm_sh1 = {
        .name = "SH1",
+       .enable_mask = 0x1,
        .num_nodes = 13,
        .nodes = { &alm_gpu_tcu, &alm_sys_tcu,
                   &chm_apps, &qnm_gpu,
@@ -1608,6 +1613,7 @@ static struct qcom_icc_bcm bcm_sn0 = {
 
 static struct qcom_icc_bcm bcm_sn1 = {
        .name = "SN1",
+       .enable_mask = 0x1,
        .num_nodes = 3,
        .nodes = { &qhm_gic, &xm_gic,
                   &qns_gemnoc_gc },
@@ -1633,6 +1639,7 @@ static struct qcom_icc_bcm bcm_sn7 = {
 
 static struct qcom_icc_bcm bcm_acv_disp = {
        .name = "ACV",
+       .enable_mask = 0x1,
        .num_nodes = 1,
        .nodes = { &ebi_disp },
 };
@@ -1657,12 +1664,14 @@ static struct qcom_icc_bcm bcm_sh0_disp = {
 
 static struct qcom_icc_bcm bcm_sh1_disp = {
        .name = "SH1",
+       .enable_mask = 0x1,
        .num_nodes = 2,
        .nodes = { &qnm_mnoc_hf_disp, &qnm_pcie_disp },
 };
 
 static struct qcom_icc_bcm bcm_acv_cam_ife_0 = {
        .name = "ACV",
+       .enable_mask = 0x0,
        .num_nodes = 1,
        .nodes = { &ebi_cam_ife_0 },
 };
@@ -1681,6 +1690,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_0 = {
 
 static struct qcom_icc_bcm bcm_mm1_cam_ife_0 = {
        .name = "MM1",
+       .enable_mask = 0x1,
        .num_nodes = 4,
        .nodes = { &qnm_camnoc_hf_cam_ife_0, &qnm_camnoc_icp_cam_ife_0,
                   &qnm_camnoc_sf_cam_ife_0, &qns_mem_noc_sf_cam_ife_0 },
@@ -1694,6 +1704,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_0 = {
 
 static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = {
        .name = "SH1",
+       .enable_mask = 0x1,
        .num_nodes = 3,
        .nodes = { &qnm_mnoc_hf_cam_ife_0, &qnm_mnoc_sf_cam_ife_0,
                   &qnm_pcie_cam_ife_0 },
@@ -1701,6 +1712,7 @@ static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = {
 
 static struct qcom_icc_bcm bcm_acv_cam_ife_1 = {
        .name = "ACV",
+       .enable_mask = 0x0,
        .num_nodes = 1,
        .nodes = { &ebi_cam_ife_1 },
 };
@@ -1719,6 +1731,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_1 = {
 
 static struct qcom_icc_bcm bcm_mm1_cam_ife_1 = {
        .name = "MM1",
+       .enable_mask = 0x1,
        .num_nodes = 4,
        .nodes = { &qnm_camnoc_hf_cam_ife_1, &qnm_camnoc_icp_cam_ife_1,
                   &qnm_camnoc_sf_cam_ife_1, &qns_mem_noc_sf_cam_ife_1 },
@@ -1732,6 +1745,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_1 = {
 
 static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = {
        .name = "SH1",
+       .enable_mask = 0x1,
        .num_nodes = 3,
        .nodes = { &qnm_mnoc_hf_cam_ife_1, &qnm_mnoc_sf_cam_ife_1,
                   &qnm_pcie_cam_ife_1 },
@@ -1739,6 +1753,7 @@ static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = {
 
 static struct qcom_icc_bcm bcm_acv_cam_ife_2 = {
        .name = "ACV",
+       .enable_mask = 0x0,
        .num_nodes = 1,
        .nodes = { &ebi_cam_ife_2 },
 };
@@ -1757,6 +1772,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_2 = {
 
 static struct qcom_icc_bcm bcm_mm1_cam_ife_2 = {
        .name = "MM1",
+       .enable_mask = 0x1,
        .num_nodes = 4,
        .nodes = { &qnm_camnoc_hf_cam_ife_2, &qnm_camnoc_icp_cam_ife_2,
                   &qnm_camnoc_sf_cam_ife_2, &qns_mem_noc_sf_cam_ife_2 },
@@ -1770,6 +1786,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_2 = {
 
 static struct qcom_icc_bcm bcm_sh1_cam_ife_2 = {
        .name = "SH1",
+       .enable_mask = 0x1,
        .num_nodes = 3,
        .nodes = { &qnm_mnoc_hf_cam_ife_2, &qnm_mnoc_sf_cam_ife_2,
                   &qnm_pcie_cam_ife_2 },
index c0331b26801087ad461b6c0f09dfc59e324badea..fe391de1aba326242633a6b2e12a13b778acd3f6 100644 (file)
@@ -839,7 +839,7 @@ hfcpci_fill_fifo(struct bchannel *bch)
                *z1t = cpu_to_le16(new_z1);     /* now send data */
                if (bch->tx_idx < bch->tx_skb->len)
                        return;
-               dev_kfree_skb(bch->tx_skb);
+               dev_kfree_skb_any(bch->tx_skb);
                if (get_next_bframe(bch))
                        goto next_t_frame;
                return;
@@ -895,7 +895,7 @@ hfcpci_fill_fifo(struct bchannel *bch)
        }
        bz->za[new_f1].z1 = cpu_to_le16(new_z1);        /* for next buffer */
        bz->f1 = new_f1;        /* next frame */
-       dev_kfree_skb(bch->tx_skb);
+       dev_kfree_skb_any(bch->tx_skb);
        get_next_bframe(bch);
 }
 
@@ -1119,7 +1119,7 @@ tx_birq(struct bchannel *bch)
        if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
                hfcpci_fill_fifo(bch);
        else {
-               dev_kfree_skb(bch->tx_skb);
+               dev_kfree_skb_any(bch->tx_skb);
                if (get_next_bframe(bch))
                        hfcpci_fill_fifo(bch);
        }
@@ -2277,7 +2277,7 @@ _hfcpci_softirq(struct device *dev, void *unused)
                return 0;
 
        if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) {
-               spin_lock(&hc->lock);
+               spin_lock_irq(&hc->lock);
                bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
                if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */
                        main_rec_hfcpci(bch);
@@ -2288,7 +2288,7 @@ _hfcpci_softirq(struct device *dev, void *unused)
                        main_rec_hfcpci(bch);
                        tx_birq(bch);
                }
-               spin_unlock(&hc->lock);
+               spin_unlock_irq(&hc->lock);
        }
        return 0;
 }
index fa09d511a8eda23cfc65ac42c1a998659584d559..baf31258f5c900654565da9f9659bee9e900a412 100644 (file)
@@ -247,7 +247,7 @@ extern void dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp);
 extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id);
 extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb);
 extern void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb);
-extern void dsp_cmx_send(void *arg);
+extern void dsp_cmx_send(struct timer_list *arg);
 extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb);
 extern int dsp_cmx_del_conf_member(struct dsp *dsp);
 extern int dsp_cmx_del_conf(struct dsp_conf *conf);
index 357b87592eb48c598afe0ef3d4cac81ba7542d7f..61cb45c5d0d8403d0c8dc61eb31ce04f4acca460 100644 (file)
@@ -1614,7 +1614,7 @@ static u16        dsp_count; /* last sample count */
 static int     dsp_count_valid; /* if we have last sample count */
 
 void
-dsp_cmx_send(void *arg)
+dsp_cmx_send(struct timer_list *arg)
 {
        struct dsp_conf *conf;
        struct dsp_conf_member *member;
index 386084530c2f85346ce164d1705918b0417eb5dc..fae95f166688336bf60850b0588f6add0f1ca352 100644 (file)
@@ -1195,7 +1195,7 @@ static int __init dsp_init(void)
        }
 
        /* set sample timer */
-       timer_setup(&dsp_spl_tl, (void *)dsp_cmx_send, 0);
+       timer_setup(&dsp_spl_tl, dsp_cmx_send, 0);
        dsp_spl_tl.expires = jiffies + dsp_tics;
        dsp_spl_jiffies = dsp_spl_tl.expires;
        add_timer(&dsp_spl_tl);
index 40cb3cb87ba17def35144f51729a64bb59b56e13..60425c99a2b8bb0d39137154abf9ef9b57a33805 100644 (file)
@@ -1310,6 +1310,8 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
        jpeg->dev = &pdev->dev;
        jpeg->variant = of_device_get_match_data(jpeg->dev);
 
+       platform_set_drvdata(pdev, jpeg);
+
        ret = devm_of_platform_populate(&pdev->dev);
        if (ret) {
                v4l2_err(&jpeg->v4l2_dev, "Master of platform populate failed.");
@@ -1381,8 +1383,6 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
                  jpeg->variant->dev_name, jpeg->vdev->num,
                  VIDEO_MAJOR, jpeg->vdev->minor);
 
-       platform_set_drvdata(pdev, jpeg);
-
        pm_runtime_enable(&pdev->dev);
 
        return 0;
index 0bd2613b9320f41b696ae91cd970dc2cb8d668a1..791bde67f439c0016d0d9f070424165aeab48c39 100644 (file)
@@ -9,7 +9,9 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/math.h>
 #include <linux/mfd/syscon.h>
+#include <linux/minmax.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
@@ -1137,8 +1139,9 @@ __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt,
         * TODO: Implement configurable stride support.
         */
        walign = 8 * 8 / cc->bpp;
-       v4l_bound_align_image(&pixfmt->width, 1, 0xffff, walign,
-                             &pixfmt->height, 1, 0xffff, 1, 0);
+       pixfmt->width = clamp(round_up(pixfmt->width, walign), walign,
+                             round_down(65535U, walign));
+       pixfmt->height = clamp(pixfmt->height, 1U, 65535U);
 
        pixfmt->bytesperline = pixfmt->width * cc->bpp / 8;
        pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
index 7f0802a5518c35fe21c1f2f683d23f137d6432ac..3418d2dd93711669a0548d411a3723dabe65be66 100644 (file)
@@ -251,8 +251,8 @@ int pkt_session_unset_buffers(struct hfi_session_release_buffer_pkt *pkt,
 
                pkt->extradata_size = 0;
                pkt->shdr.hdr.size =
-                       struct_size((struct hfi_session_set_buffers_pkt *)0,
-                                   buffer_info, bd->num_buffers);
+                       struct_size_t(struct hfi_session_set_buffers_pkt,
+                                     buffer_info, bd->num_buffers);
        }
 
        pkt->response_req = bd->response_required;
index 5ac2a424b13df6c8e5e86264812094f399e35859..f4988f03640aecfec11a09e6538aa38abf7179ca 100644 (file)
@@ -45,7 +45,7 @@ static int uvc_control_add_xu_mapping(struct uvc_video_chain *chain,
        map->menu_names = NULL;
        map->menu_mapping = NULL;
 
-       map->menu_mask = BIT_MASK(xmap->menu_count);
+       map->menu_mask = GENMASK(xmap->menu_count - 1, 0);
 
        size = xmap->menu_count * sizeof(*map->menu_mapping);
        map->menu_mapping = kzalloc(size, GFP_KERNEL);
index 4a750da1c12aaee09a1e17ea0108b01ac55aa52d..deb6e65b59afc4ed5bbfee5753fbbd2c4a5ac1cb 100644 (file)
@@ -755,6 +755,43 @@ const char *const tegra_mc_error_names[8] = {
        [6] = "SMMU translation error",
 };
 
+struct icc_node *tegra_mc_icc_xlate(struct of_phandle_args *spec, void *data)
+{
+       struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
+       struct icc_node *node;
+
+       list_for_each_entry(node, &mc->provider.nodes, node_list) {
+               if (node->id == spec->args[0])
+                       return node;
+       }
+
+       /*
+        * If a client driver calls devm_of_icc_get() before the MC driver
+        * is probed, then return EPROBE_DEFER to the client driver.
+        */
+       return ERR_PTR(-EPROBE_DEFER);
+}
+
+static int tegra_mc_icc_get(struct icc_node *node, u32 *average, u32 *peak)
+{
+       *average = 0;
+       *peak = 0;
+
+       return 0;
+}
+
+static int tegra_mc_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+       return 0;
+}
+
+const struct tegra_mc_icc_ops tegra_mc_icc_ops = {
+       .xlate = tegra_mc_icc_xlate,
+       .aggregate = icc_std_aggregate,
+       .get_bw = tegra_mc_icc_get,
+       .set = tegra_mc_icc_set,
+};
+
 /*
  * Memory Controller (MC) has few Memory Clients that are issuing memory
  * bandwidth allocation requests to the MC interconnect provider. The MC
index b2416ee3ac26ac68200d63a594f0db5794913969..26035ac3a1eb51a3d8ce3830427b4412b48baf3c 100644 (file)
@@ -1355,6 +1355,7 @@ const struct tegra_mc_soc tegra194_mc_soc = {
                   MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
        .has_addr_hi_reg = true,
        .ops = &tegra186_mc_ops,
+       .icc_ops = &tegra_mc_icc_ops,
        .ch_intmask = 0x00000f00,
        .global_intstatus_channel_shift = 8,
 };
index 8e873a7bc34f29b98fc762e22b801037d58bffec..8fb83b39f5f5b1903601da493b3f5cc2b8bff448 100644 (file)
@@ -827,7 +827,7 @@ static int tegra234_mc_icc_set(struct icc_node *src, struct icc_node *dst)
                return 0;
 
        if (!mc->bwmgr_mrq_supported)
-               return -EINVAL;
+               return 0;
 
        if (!mc->bpmp) {
                dev_err(mc->dev, "BPMP reference NULL\n");
@@ -874,7 +874,7 @@ static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
        struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
 
        if (!mc->bwmgr_mrq_supported)
-               return -EINVAL;
+               return 0;
 
        if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 ||
            node->id == TEGRA_ICC_MC_CPU_CLUSTER1 ||
@@ -889,27 +889,6 @@ static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
        return 0;
 }
 
-static struct icc_node*
-tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data)
-{
-       struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
-       unsigned int cl_id = spec->args[0];
-       struct icc_node *node;
-
-       list_for_each_entry(node, &mc->provider.nodes, node_list) {
-               if (node->id != cl_id)
-                       continue;
-
-               return node;
-       }
-
-       /*
-        * If a client driver calls devm_of_icc_get() before the MC driver
-        * is probed, then return EPROBE_DEFER to the client driver.
-        */
-       return ERR_PTR(-EPROBE_DEFER);
-}
-
 static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
 {
        *avg = 0;
@@ -919,7 +898,7 @@ static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea
 }
 
 static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
-       .xlate = tegra234_mc_of_icc_xlate,
+       .xlate = tegra_mc_icc_xlate,
        .aggregate = tegra234_mc_icc_aggregate,
        .get_bw = tegra234_mc_icc_get_init_bw,
        .set = tegra234_mc_icc_set,
index d676cf63a9669180b43bf3c7b13c6f4cc715c483..3dae5e3a16976f0e229523544396e21670747cae 100644 (file)
@@ -195,7 +195,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
                }
        }
 
-       if (option->force_clkreq_0)
+       if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG)
                rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
                                FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
        else
index cfebad51d1d80b72b6565bf9508c9a68b0fec35c..f4ab09439da70c977ea29bbb63e1ae8d80a1f08f 100644 (file)
@@ -435,17 +435,10 @@ static void rts5228_init_from_cfg(struct rtsx_pcr *pcr)
                        option->ltr_enabled = false;
                }
        }
-
-       if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
-                               | PM_L1_1_EN | PM_L1_2_EN))
-               option->force_clkreq_0 = false;
-       else
-               option->force_clkreq_0 = true;
 }
 
 static int rts5228_extra_init_hw(struct rtsx_pcr *pcr)
 {
-       struct rtsx_cr_option *option = &pcr->option;
 
        rtsx_pci_write_register(pcr, RTS5228_AUTOLOAD_CFG1,
                        CD_RESUME_EN_MASK, CD_RESUME_EN_MASK);
@@ -476,17 +469,6 @@ static int rts5228_extra_init_hw(struct rtsx_pcr *pcr)
        else
                rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
 
-       /*
-        * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
-        * to drive low, and we forcibly request clock.
-        */
-       if (option->force_clkreq_0)
-               rtsx_pci_write_register(pcr, PETXCFG,
-                                FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
-       else
-               rtsx_pci_write_register(pcr, PETXCFG,
-                                FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
-
        rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
 
        if (pcr->rtd3_en) {
index 91d240dd68faa73e18d894f7fd6cde95c52a802a..47ab72a43256bc2ce1aa6fd3ece81bc50b78ca6d 100644 (file)
@@ -327,12 +327,11 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
                }
        }
 
-
        /*
         * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
         * to drive low, and we forcibly request clock.
         */
-       if (option->force_clkreq_0)
+       if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG)
                rtsx_pci_write_register(pcr, PETXCFG,
                        FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
        else
index 9b42b20a3e5ae97771aed280b88abcafa61569d4..79b18f6f73a8a83cd6865721f60509a225b8df6e 100644 (file)
@@ -517,17 +517,10 @@ static void rts5260_init_from_cfg(struct rtsx_pcr *pcr)
                        option->ltr_enabled = false;
                }
        }
-
-       if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
-                               | PM_L1_1_EN | PM_L1_2_EN))
-               option->force_clkreq_0 = false;
-       else
-               option->force_clkreq_0 = true;
 }
 
 static int rts5260_extra_init_hw(struct rtsx_pcr *pcr)
 {
-       struct rtsx_cr_option *option = &pcr->option;
 
        /* Set mcu_cnt to 7 to ensure data can be sampled properly */
        rtsx_pci_write_register(pcr, 0xFC03, 0x7F, 0x07);
@@ -546,17 +539,6 @@ static int rts5260_extra_init_hw(struct rtsx_pcr *pcr)
 
        rts5260_init_hw(pcr);
 
-       /*
-        * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
-        * to drive low, and we forcibly request clock.
-        */
-       if (option->force_clkreq_0)
-               rtsx_pci_write_register(pcr, PETXCFG,
-                                FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
-       else
-               rtsx_pci_write_register(pcr, PETXCFG,
-                                FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
-
        rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00);
 
        return 0;
index b1e76030cafda93d1810b4f37d341ca0c0b0c3bb..94af6bf8a25a6f3c36bc3084f5cd95e7926a1fb5 100644 (file)
@@ -498,17 +498,10 @@ static void rts5261_init_from_cfg(struct rtsx_pcr *pcr)
                        option->ltr_enabled = false;
                }
        }
-
-       if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
-                               | PM_L1_1_EN | PM_L1_2_EN))
-               option->force_clkreq_0 = false;
-       else
-               option->force_clkreq_0 = true;
 }
 
 static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
 {
-       struct rtsx_cr_option *option = &pcr->option;
        u32 val;
 
        rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1,
@@ -554,17 +547,6 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
        else
                rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
 
-       /*
-        * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
-        * to drive low, and we forcibly request clock.
-        */
-       if (option->force_clkreq_0)
-               rtsx_pci_write_register(pcr, PETXCFG,
-                                FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
-       else
-               rtsx_pci_write_register(pcr, PETXCFG,
-                                FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
-
        rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
 
        if (pcr->rtd3_en) {
index 32b7783e9d4faa5cf921329c72a4a4a4f246ded6..a3f4b52bb159f0c1287b692e7484815bddff8614 100644 (file)
@@ -1326,8 +1326,11 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
                        return err;
        }
 
-       if (pcr->aspm_mode == ASPM_MODE_REG)
+       if (pcr->aspm_mode == ASPM_MODE_REG) {
                rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0x30, 0x30);
+               rtsx_pci_write_register(pcr, PETXCFG,
+                               FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
+       }
 
        /* No CD interrupt if probing driver with card inserted.
         * So we need to initialize pcr->card_exist here.
index b488f704f104eb81a0108d1c29fbed09a62f79d8..05e2c151e63217180239c8a58d20b9222519c3c6 100644 (file)
@@ -13,6 +13,8 @@
 
 #include <linux/mfd/tps6594.h>
 
+#define TPS6594_DEV_REV_1 0x08
+
 static irqreturn_t tps6594_esm_isr(int irq, void *dev_id)
 {
        struct platform_device *pdev = dev_id;
@@ -32,11 +34,26 @@ static int tps6594_esm_probe(struct platform_device *pdev)
 {
        struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
        struct device *dev = &pdev->dev;
+       unsigned int rev;
        int irq;
        int ret;
        int i;
 
-       for (i = 0 ; i < pdev->num_resources ; i++) {
+       /*
+        * Due to a bug in revision 1 of the PMIC, the GPIO3 used for the
+        * SoC ESM function is used to power the load switch instead.
+        * As a consequence, ESM can not be used on those PMIC.
+        * Check the version and return an error in case of revision 1.
+        */
+       ret = regmap_read(tps->regmap, TPS6594_REG_DEV_REV, &rev);
+       if (ret)
+               return dev_err_probe(dev, ret,
+                                    "Failed to read PMIC revision\n");
+       if (rev == TPS6594_DEV_REV_1)
+               return dev_err_probe(dev, -ENODEV,
+                             "ESM not supported for revision 1 PMIC\n");
+
+       for (i = 0; i < pdev->num_resources; i++) {
                irq = platform_get_irq_byname(pdev, pdev->resource[i].name);
                if (irq < 0)
                        return dev_err_probe(dev, irq, "Failed to get %s irq\n",
index f701efb1fa785518ada2f2ef8f1f504cc7e4f726..b6f4be25b31b05b4d57aec59ff401e72152ecb10 100644 (file)
@@ -2097,14 +2097,14 @@ static void mmc_blk_mq_poll_completion(struct mmc_queue *mq,
        mmc_blk_urgent_bkops(mq, mqrq);
 }
 
-static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req)
+static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type)
 {
        unsigned long flags;
        bool put_card;
 
        spin_lock_irqsave(&mq->lock, flags);
 
-       mq->in_flight[mmc_issue_type(mq, req)] -= 1;
+       mq->in_flight[issue_type] -= 1;
 
        put_card = (mmc_tot_in_flight(mq) == 0);
 
@@ -2117,6 +2117,7 @@ static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req)
 static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req,
                                bool can_sleep)
 {
+       enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
        struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
        struct mmc_request *mrq = &mqrq->brq.mrq;
        struct mmc_host *host = mq->card->host;
@@ -2136,7 +2137,7 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req,
                        blk_mq_complete_request(req);
        }
 
-       mmc_blk_mq_dec_in_flight(mq, req);
+       mmc_blk_mq_dec_in_flight(mq, issue_type);
 }
 
 void mmc_blk_mq_recovery(struct mmc_queue *mq)
index 2d002c81dcf36c27027bc4707d0316146b46cc1e..d0d6ffcf78d40f7a5eeaa0d96b7af18774057e84 100644 (file)
@@ -338,13 +338,7 @@ static void moxart_transfer_pio(struct moxart_host *host)
                                return;
                        }
                        for (len = 0; len < remain && len < host->fifo_width;) {
-                               /* SCR data must be read in big endian. */
-                               if (data->mrq->cmd->opcode == SD_APP_SEND_SCR)
-                                       *sgp = ioread32be(host->base +
-                                                         REG_DATA_WINDOW);
-                               else
-                                       *sgp = ioread32(host->base +
-                                                       REG_DATA_WINDOW);
+                               *sgp = ioread32(host->base + REG_DATA_WINDOW);
                                sgp++;
                                len += 4;
                        }
index a202a69a4b0843c6560675c5d2da504449f7719b..3215063bcf86806d9fd31b915e51e9383b839cbb 100644 (file)
@@ -29,9 +29,16 @@ struct f_sdhost_priv {
        bool enable_cmd_dat_delay;
 };
 
+static void *sdhci_f_sdhost_priv(struct sdhci_host *host)
+{
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+       return sdhci_pltfm_priv(pltfm_host);
+}
+
 static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
 {
-       struct f_sdhost_priv *priv = sdhci_priv(host);
+       struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
        u32 ctrl = 0;
 
        usleep_range(2500, 3000);
@@ -64,7 +71,7 @@ static unsigned int sdhci_f_sdh30_get_min_clock(struct sdhci_host *host)
 
 static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask)
 {
-       struct f_sdhost_priv *priv = sdhci_priv(host);
+       struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
        u32 ctl;
 
        if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0)
@@ -95,30 +102,32 @@ static const struct sdhci_ops sdhci_f_sdh30_ops = {
        .set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
+static const struct sdhci_pltfm_data sdhci_f_sdh30_pltfm_data = {
+       .ops = &sdhci_f_sdh30_ops,
+       .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
+               | SDHCI_QUIRK_INVERTED_WRITE_PROTECT,
+       .quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE
+               |  SDHCI_QUIRK2_TUNING_WORK_AROUND,
+};
+
 static int sdhci_f_sdh30_probe(struct platform_device *pdev)
 {
        struct sdhci_host *host;
        struct device *dev = &pdev->dev;
-       int irq, ctrl = 0, ret = 0;
+       int ctrl = 0, ret = 0;
        struct f_sdhost_priv *priv;
+       struct sdhci_pltfm_host *pltfm_host;
        u32 reg = 0;
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
-       host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv));
+       host = sdhci_pltfm_init(pdev, &sdhci_f_sdh30_pltfm_data,
+                               sizeof(struct f_sdhost_priv));
        if (IS_ERR(host))
                return PTR_ERR(host);
 
-       priv = sdhci_priv(host);
+       pltfm_host = sdhci_priv(host);
+       priv = sdhci_pltfm_priv(pltfm_host);
        priv->dev = dev;
 
-       host->quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
-                      SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
-       host->quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE |
-                       SDHCI_QUIRK2_TUNING_WORK_AROUND;
-
        priv->enable_cmd_dat_delay = device_property_read_bool(dev,
                                                "fujitsu,cmd-dat-delay-select");
 
@@ -126,18 +135,6 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev)
        if (ret)
                goto err;
 
-       platform_set_drvdata(pdev, host);
-
-       host->hw_name = "f_sdh30";
-       host->ops = &sdhci_f_sdh30_ops;
-       host->irq = irq;
-
-       host->ioaddr = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(host->ioaddr)) {
-               ret = PTR_ERR(host->ioaddr);
-               goto err;
-       }
-
        if (dev_of_node(dev)) {
                sdhci_get_of_property(pdev);
 
@@ -204,24 +201,24 @@ err_rst:
 err_clk:
        clk_disable_unprepare(priv->clk_iface);
 err:
-       sdhci_free_host(host);
+       sdhci_pltfm_free(pdev);
+
        return ret;
 }
 
 static int sdhci_f_sdh30_remove(struct platform_device *pdev)
 {
        struct sdhci_host *host = platform_get_drvdata(pdev);
-       struct f_sdhost_priv *priv = sdhci_priv(host);
+       struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
+       struct clk *clk_iface = priv->clk_iface;
+       struct reset_control *rst = priv->rst;
+       struct clk *clk = priv->clk;
 
-       sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) ==
-                         0xffffffff);
-
-       reset_control_assert(priv->rst);
-       clk_disable_unprepare(priv->clk);
-       clk_disable_unprepare(priv->clk_iface);
+       sdhci_pltfm_unregister(pdev);
 
-       sdhci_free_host(host);
-       platform_set_drvdata(pdev, NULL);
+       reset_control_assert(rst);
+       clk_disable_unprepare(clk);
+       clk_disable_unprepare(clk_iface);
 
        return 0;
 }
index db5e0dcdfa7f32be47ad2b86331f838b14afb148..2bdebeb1f8e49c92fa009ccb38dd4e788a2daaf7 100644 (file)
@@ -863,11 +863,9 @@ static int spmmc_drv_probe(struct platform_device *pdev)
        struct spmmc_host *host;
        int ret = 0;
 
-       mmc = mmc_alloc_host(sizeof(*host), &pdev->dev);
-       if (!mmc) {
-               ret = -ENOMEM;
-               goto probe_free_host;
-       }
+       mmc = devm_mmc_alloc_host(&pdev->dev, sizeof(struct spmmc_host));
+       if (!mmc)
+               return -ENOMEM;
 
        host = mmc_priv(mmc);
        host->mmc = mmc;
@@ -902,7 +900,7 @@ static int spmmc_drv_probe(struct platform_device *pdev)
 
        ret = mmc_of_parse(mmc);
        if (ret)
-               goto probe_free_host;
+               goto clk_disable;
 
        mmc->ops = &spmmc_ops;
        mmc->f_min = SPMMC_MIN_CLK;
@@ -911,7 +909,7 @@ static int spmmc_drv_probe(struct platform_device *pdev)
 
        ret = mmc_regulator_get_supply(mmc);
        if (ret)
-               goto probe_free_host;
+               goto clk_disable;
 
        if (!mmc->ocr_avail)
                mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
@@ -927,14 +925,17 @@ static int spmmc_drv_probe(struct platform_device *pdev)
        host->tuning_info.enable_tuning = 1;
        pm_runtime_set_active(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
-       mmc_add_host(mmc);
+       ret = mmc_add_host(mmc);
+       if (ret)
+               goto pm_disable;
 
-       return ret;
+       return 0;
 
-probe_free_host:
-       if (mmc)
-               mmc_free_host(mmc);
+pm_disable:
+       pm_runtime_disable(&pdev->dev);
 
+clk_disable:
+       clk_disable_unprepare(host->clk);
        return ret;
 }
 
@@ -948,7 +949,6 @@ static int spmmc_drv_remove(struct platform_device *dev)
        pm_runtime_put_noidle(&dev->dev);
        pm_runtime_disable(&dev->dev);
        platform_set_drvdata(dev, NULL);
-       mmc_free_host(host->mmc);
 
        return 0;
 }
index 521af9251f33595613f73862dbf395cd886c713c..bf2a92fba0ed81cb347b6c95693223254e51b6ff 100644 (file)
@@ -1705,8 +1705,6 @@ static int wbsd_init(struct device *dev, int base, int irq, int dma,
 
                wbsd_release_resources(host);
                wbsd_free_mmc(dev);
-
-               mmc_free_host(mmc);
                return ret;
        }
 
index 086426139173f39d832f3bca00ff475eb6106c8e..7366e85c09fd987c494fd73aa06b440a0955c199 100644 (file)
@@ -135,7 +135,7 @@ static int fun_exec_op(struct nand_chip *chip, const struct nand_operation *op,
        unsigned int i;
        int ret;
 
-       if (op->cs > NAND_MAX_CHIPS)
+       if (op->cs >= NAND_MAX_CHIPS)
                return -EINVAL;
 
        if (check_only)
index d3faf80866314622aefbfb9d927124a3ebd72736..b10011dec1e62c5733f6a8017806cc1cb7374ded 100644 (file)
@@ -1278,7 +1278,6 @@ static int meson_nand_attach_chip(struct nand_chip *nand)
        struct meson_nfc *nfc = nand_get_controller_data(nand);
        struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
        struct mtd_info *mtd = nand_to_mtd(nand);
-       int nsectors = mtd->writesize / 1024;
        int raw_writesize;
        int ret;
 
@@ -1304,7 +1303,7 @@ static int meson_nand_attach_chip(struct nand_chip *nand)
        nand->options |= NAND_NO_SUBPAGE_WRITE;
 
        ret = nand_ecc_choose_conf(nand, nfc->data->ecc_caps,
-                                  mtd->oobsize - 2 * nsectors);
+                                  mtd->oobsize - 2);
        if (ret) {
                dev_err(nfc->dev, "failed to ECC init\n");
                return -EINVAL;
index 6e1eac6644a66ee2b774565e0e2d15a31e417299..4a97d4a76454a2a8af234c040da041545d50df8d 100644 (file)
@@ -177,17 +177,17 @@ static void elm_load_syndrome(struct elm_info *info,
                        switch (info->bch_type) {
                        case BCH8_ECC:
                                /* syndrome fragment 0 = ecc[9-12B] */
-                               val = cpu_to_be32(*(u32 *) &ecc[9]);
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[9]);
                                elm_write_reg(info, offset, val);
 
                                /* syndrome fragment 1 = ecc[5-8B] */
                                offset += 4;
-                               val = cpu_to_be32(*(u32 *) &ecc[5]);
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[5]);
                                elm_write_reg(info, offset, val);
 
                                /* syndrome fragment 2 = ecc[1-4B] */
                                offset += 4;
-                               val = cpu_to_be32(*(u32 *) &ecc[1]);
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[1]);
                                elm_write_reg(info, offset, val);
 
                                /* syndrome fragment 3 = ecc[0B] */
@@ -197,35 +197,35 @@ static void elm_load_syndrome(struct elm_info *info,
                                break;
                        case BCH4_ECC:
                                /* syndrome fragment 0 = ecc[20-52b] bits */
-                               val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) |
+                               val = ((__force u32)cpu_to_be32(*(u32 *)&ecc[3]) >> 4) |
                                        ((ecc[2] & 0xf) << 28);
                                elm_write_reg(info, offset, val);
 
                                /* syndrome fragment 1 = ecc[0-20b] bits */
                                offset += 4;
-                               val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12;
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 12;
                                elm_write_reg(info, offset, val);
                                break;
                        case BCH16_ECC:
-                               val = cpu_to_be32(*(u32 *) &ecc[22]);
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[22]);
                                elm_write_reg(info, offset, val);
                                offset += 4;
-                               val = cpu_to_be32(*(u32 *) &ecc[18]);
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[18]);
                                elm_write_reg(info, offset, val);
                                offset += 4;
-                               val = cpu_to_be32(*(u32 *) &ecc[14]);
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[14]);
                                elm_write_reg(info, offset, val);
                                offset += 4;
-                               val = cpu_to_be32(*(u32 *) &ecc[10]);
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[10]);
                                elm_write_reg(info, offset, val);
                                offset += 4;
-                               val = cpu_to_be32(*(u32 *) &ecc[6]);
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[6]);
                                elm_write_reg(info, offset, val);
                                offset += 4;
-                               val = cpu_to_be32(*(u32 *) &ecc[2]);
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[2]);
                                elm_write_reg(info, offset, val);
                                offset += 4;
-                               val = cpu_to_be32(*(u32 *) &ecc[0]) >> 16;
+                               val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 16;
                                elm_write_reg(info, offset, val);
                                break;
                        default:
index 2312e27362cbef83b7686150da7a896f0c085f24..5a04680342c327c403b353c8eabcf94f97b8cc40 100644 (file)
@@ -562,9 +562,10 @@ static int rk_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf,
                 *    BBM  OOB1 OOB2 OOB3 |......|  PA0  PA1  PA2  PA3
                 *
                 * The rk_nfc_ooblayout_free() function already has reserved
-                * these 4 bytes with:
+                * these 4 bytes together with 2 bytes for BBM
+                * by reducing it's length:
                 *
-                * oob_region->offset = NFC_SYS_DATA_SIZE + 2;
+                * oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2;
                 */
                if (!i)
                        memcpy(rk_nfc_oob_ptr(chip, i),
@@ -597,7 +598,7 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
        int pages_per_blk = mtd->erasesize / mtd->writesize;
        int ret = 0, i, boot_rom_mode = 0;
        dma_addr_t dma_data, dma_oob;
-       u32 reg;
+       u32 tmp;
        u8 *oob;
 
        nand_prog_page_begin_op(chip, page, 0, NULL, 0);
@@ -624,6 +625,13 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
         *
         *   0xFF 0xFF 0xFF 0xFF | BBM OOB1 OOB2 OOB3 | ...
         *
+        * The code here just swaps the first 4 bytes with the last
+        * 4 bytes without losing any data.
+        *
+        * The chip->oob_poi data layout:
+        *
+        *    BBM  OOB1 OOB2 OOB3 |......|  PA0  PA1  PA2  PA3
+        *
         * Configure the ECC algorithm supported by the boot ROM.
         */
        if ((page < (pages_per_blk * rknand->boot_blks)) &&
@@ -634,21 +642,17 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
        }
 
        for (i = 0; i < ecc->steps; i++) {
-               if (!i) {
-                       reg = 0xFFFFFFFF;
-               } else {
+               if (!i)
+                       oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
+               else
                        oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
-                       reg = oob[0] | oob[1] << 8 | oob[2] << 16 |
-                             oob[3] << 24;
-               }
 
-               if (!i && boot_rom_mode)
-                       reg = (page & (pages_per_blk - 1)) * 4;
+               tmp = oob[0] | oob[1] << 8 | oob[2] << 16 | oob[3] << 24;
 
                if (nfc->cfg->type == NFC_V9)
-                       nfc->oob_buf[i] = reg;
+                       nfc->oob_buf[i] = tmp;
                else
-                       nfc->oob_buf[i * (oob_step / 4)] = reg;
+                       nfc->oob_buf[i * (oob_step / 4)] = tmp;
        }
 
        dma_data = dma_map_single(nfc->dev, (void *)nfc->page_buf,
@@ -811,12 +815,17 @@ static int rk_nfc_read_page_hwecc(struct nand_chip *chip, u8 *buf, int oob_on,
                goto timeout_err;
        }
 
-       for (i = 1; i < ecc->steps; i++) {
-               oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
+       for (i = 0; i < ecc->steps; i++) {
+               if (!i)
+                       oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
+               else
+                       oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
+
                if (nfc->cfg->type == NFC_V9)
                        tmp = nfc->oob_buf[i];
                else
                        tmp = nfc->oob_buf[i * (oob_step / 4)];
+
                *oob++ = (u8)tmp;
                *oob++ = (u8)(tmp >> 8);
                *oob++ = (u8)(tmp >> 16);
@@ -933,12 +942,8 @@ static int rk_nfc_ooblayout_free(struct mtd_info *mtd, int section,
        if (section)
                return -ERANGE;
 
-       /*
-        * The beginning of the OOB area stores the reserved data for the NFC,
-        * the size of the reserved data is NFC_SYS_DATA_SIZE bytes.
-        */
        oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2;
-       oob_region->offset = NFC_SYS_DATA_SIZE + 2;
+       oob_region->offset = 2;
 
        return 0;
 }
index 7380b1ebaccd55d32c32c2502c63d6ae352b9e13..a80427c131216641bde9b2ae411c429716fb2a60 100644 (file)
@@ -73,7 +73,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
 {
        struct nand_device *nand = spinand_to_nand(spinand);
        u8 mbf = 0;
-       struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
+       struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf);
 
        switch (status & STATUS_ECC_MASK) {
        case STATUS_ECC_NO_BITFLIPS:
@@ -92,7 +92,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
                if (spi_mem_exec_op(spinand->spimem, &op))
                        return nanddev_get_ecc_conf(nand)->strength;
 
-               mbf >>= 4;
+               mbf = *(spinand->scratchbuf) >> 4;
 
                if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
                        return nanddev_get_ecc_conf(nand)->strength;
index 3ad58cd284d8b876864e175ffe01593563845125..f507e37593012d18f71b285a58027fbff4e0d339 100644 (file)
@@ -108,7 +108,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
 {
        struct nand_device *nand = spinand_to_nand(spinand);
        u8 mbf = 0;
-       struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
+       struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf);
 
        switch (status & STATUS_ECC_MASK) {
        case STATUS_ECC_NO_BITFLIPS:
@@ -126,7 +126,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
                if (spi_mem_exec_op(spinand->spimem, &op))
                        return nanddev_get_ecc_conf(nand)->strength;
 
-               mbf >>= 4;
+               mbf = *(spinand->scratchbuf) >> 4;
 
                if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
                        return nanddev_get_ecc_conf(nand)->strength;
index 36876aa849ede7cda8d9900589fccbcb879c6d93..15f9a80c10b9bd58096d95214b921dee5c72f48f 100644 (file)
@@ -361,7 +361,7 @@ static int cypress_nor_determine_addr_mode_by_sr1(struct spi_nor *nor,
  */
 static int cypress_nor_set_addr_mode_nbytes(struct spi_nor *nor)
 {
-       struct spi_mem_op op = {};
+       struct spi_mem_op op;
        u8 addr_mode;
        int ret;
 
@@ -492,7 +492,7 @@ s25fs256t_post_bfpt_fixup(struct spi_nor *nor,
                          const struct sfdp_parameter_header *bfpt_header,
                          const struct sfdp_bfpt *bfpt)
 {
-       struct spi_mem_op op = {};
+       struct spi_mem_op op;
        int ret;
 
        ret = cypress_nor_set_addr_mode_nbytes(nor);
index 484c9e3e5e8252b42f5060a1e402792845e2d3e9..447b06ea4fc9cecebb7d630f34b98b3d54b961a8 100644 (file)
@@ -5901,7 +5901,9 @@ void bond_setup(struct net_device *bond_dev)
 
        bond_dev->hw_features = BOND_VLAN_FEATURES |
                                NETIF_F_HW_VLAN_CTAG_RX |
-                               NETIF_F_HW_VLAN_CTAG_FILTER;
+                               NETIF_F_HW_VLAN_CTAG_FILTER |
+                               NETIF_F_HW_VLAN_STAG_RX |
+                               NETIF_F_HW_VLAN_STAG_FILTER;
 
        bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
        bond_dev->features |= bond_dev->hw_features;
index cde253d27bd0845e079393896d09546d8982c88a..72374b066f64a902f0a7428daf34e79bb77521f9 100644 (file)
@@ -1436,7 +1436,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
        if (IS_ERR(priv->clk))
                return PTR_ERR(priv->clk);
 
-       clk_prepare_enable(priv->clk);
+       ret = clk_prepare_enable(priv->clk);
+       if (ret)
+               return ret;
 
        priv->clk_mdiv = devm_clk_get_optional(&pdev->dev, "sw_switch_mdiv");
        if (IS_ERR(priv->clk_mdiv)) {
@@ -1444,7 +1446,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
                goto out_clk;
        }
 
-       clk_prepare_enable(priv->clk_mdiv);
+       ret = clk_prepare_enable(priv->clk_mdiv);
+       if (ret)
+               goto out_clk;
 
        ret = bcm_sf2_sw_rst(priv);
        if (ret) {
index b18cd170ec06cc72801046d1f6467b5c9cced4ec..6c0623f88654e73c2a8e1225bd70f69570b99f34 100644 (file)
@@ -635,10 +635,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x1030, 0x1030),
        regmap_reg_range(0x1100, 0x1115),
        regmap_reg_range(0x111a, 0x111f),
-       regmap_reg_range(0x1122, 0x1127),
-       regmap_reg_range(0x112a, 0x112b),
-       regmap_reg_range(0x1136, 0x1139),
-       regmap_reg_range(0x113e, 0x113f),
+       regmap_reg_range(0x1120, 0x112b),
+       regmap_reg_range(0x1134, 0x113b),
+       regmap_reg_range(0x113c, 0x113f),
        regmap_reg_range(0x1400, 0x1401),
        regmap_reg_range(0x1403, 0x1403),
        regmap_reg_range(0x1410, 0x1417),
@@ -669,10 +668,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x2030, 0x2030),
        regmap_reg_range(0x2100, 0x2115),
        regmap_reg_range(0x211a, 0x211f),
-       regmap_reg_range(0x2122, 0x2127),
-       regmap_reg_range(0x212a, 0x212b),
-       regmap_reg_range(0x2136, 0x2139),
-       regmap_reg_range(0x213e, 0x213f),
+       regmap_reg_range(0x2120, 0x212b),
+       regmap_reg_range(0x2134, 0x213b),
+       regmap_reg_range(0x213c, 0x213f),
        regmap_reg_range(0x2400, 0x2401),
        regmap_reg_range(0x2403, 0x2403),
        regmap_reg_range(0x2410, 0x2417),
@@ -703,10 +701,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x3030, 0x3030),
        regmap_reg_range(0x3100, 0x3115),
        regmap_reg_range(0x311a, 0x311f),
-       regmap_reg_range(0x3122, 0x3127),
-       regmap_reg_range(0x312a, 0x312b),
-       regmap_reg_range(0x3136, 0x3139),
-       regmap_reg_range(0x313e, 0x313f),
+       regmap_reg_range(0x3120, 0x312b),
+       regmap_reg_range(0x3134, 0x313b),
+       regmap_reg_range(0x313c, 0x313f),
        regmap_reg_range(0x3400, 0x3401),
        regmap_reg_range(0x3403, 0x3403),
        regmap_reg_range(0x3410, 0x3417),
@@ -737,10 +734,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x4030, 0x4030),
        regmap_reg_range(0x4100, 0x4115),
        regmap_reg_range(0x411a, 0x411f),
-       regmap_reg_range(0x4122, 0x4127),
-       regmap_reg_range(0x412a, 0x412b),
-       regmap_reg_range(0x4136, 0x4139),
-       regmap_reg_range(0x413e, 0x413f),
+       regmap_reg_range(0x4120, 0x412b),
+       regmap_reg_range(0x4134, 0x413b),
+       regmap_reg_range(0x413c, 0x413f),
        regmap_reg_range(0x4400, 0x4401),
        regmap_reg_range(0x4403, 0x4403),
        regmap_reg_range(0x4410, 0x4417),
@@ -771,10 +767,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x5030, 0x5030),
        regmap_reg_range(0x5100, 0x5115),
        regmap_reg_range(0x511a, 0x511f),
-       regmap_reg_range(0x5122, 0x5127),
-       regmap_reg_range(0x512a, 0x512b),
-       regmap_reg_range(0x5136, 0x5139),
-       regmap_reg_range(0x513e, 0x513f),
+       regmap_reg_range(0x5120, 0x512b),
+       regmap_reg_range(0x5134, 0x513b),
+       regmap_reg_range(0x513c, 0x513f),
        regmap_reg_range(0x5400, 0x5401),
        regmap_reg_range(0x5403, 0x5403),
        regmap_reg_range(0x5410, 0x5417),
index c7d51a539451e419ff5d0ef2a3966793f0e16d66..7af2f08a62f14b7ac38e56e9ca656a3830b4a839 100644 (file)
@@ -3034,6 +3034,14 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
 
        /* If there is a GPIO connected to the reset pin, toggle it */
        if (gpiod) {
+               /* If the switch has just been reset and not yet completed
+                * loading EEPROM, the reset may interrupt the I2C transaction
+                * mid-byte, causing the first EEPROM read after the reset
+                * from the wrong location resulting in the switch booting
+                * to wrong mode and inoperable.
+                */
+               mv88e6xxx_g1_wait_eeprom_done(chip);
+
                gpiod_set_value_cansleep(gpiod, 1);
                usleep_range(10000, 20000);
                gpiod_set_value_cansleep(gpiod, 0);
index 8da46d284e35649a7b68a4148593e2a03aa5d8c7..bef879c6d500b720fd6724409501ead52198a514 100644 (file)
@@ -1625,8 +1625,10 @@ static void felix_teardown(struct dsa_switch *ds)
        struct felix *felix = ocelot_to_felix(ocelot);
        struct dsa_port *dp;
 
+       rtnl_lock();
        if (felix->tag_proto_ops)
                felix->tag_proto_ops->teardown(ds);
+       rtnl_unlock();
 
        dsa_switch_for_each_available_port(dp, ds)
                ocelot_deinit_port(ocelot, dp->index);
index 392ec09a1d8a6f51a3af21a8cbccfc4419359568..3e4fb3c3e8342ad3dbf7aa32df03fc4ce57e3cad 100644 (file)
@@ -1793,11 +1793,9 @@ static int b44_nway_reset(struct net_device *dev)
        b44_readphy(bp, MII_BMCR, &bmcr);
        b44_readphy(bp, MII_BMCR, &bmcr);
        r = -EINVAL;
-       if (bmcr & BMCR_ANENABLE) {
-               b44_writephy(bp, MII_BMCR,
-                            bmcr | BMCR_ANRESTART);
-               r = 0;
-       }
+       if (bmcr & BMCR_ANENABLE)
+               r = b44_writephy(bp, MII_BMCR,
+                                bmcr | BMCR_ANRESTART);
        spin_unlock_irq(&bp->lock);
 
        return r;
index e5b54e6025bece04206b69ba9556908aaa53e46e..1eb490c48c52e974a669e712706bb1fd5904a6c4 100644 (file)
@@ -633,12 +633,13 @@ tx_kick_pending:
        return NETDEV_TX_OK;
 }
 
-static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
 {
        struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
        struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index);
        u16 cons = txr->tx_cons;
        struct pci_dev *pdev = bp->pdev;
+       int nr_pkts = bnapi->tx_pkts;
        int i;
        unsigned int tx_bytes = 0;
 
@@ -688,6 +689,7 @@ next_tx_int:
                dev_kfree_skb_any(skb);
        }
 
+       bnapi->tx_pkts = 0;
        WRITE_ONCE(txr->tx_cons, cons);
 
        __netif_txq_completed_wake(txq, nr_pkts, tx_bytes,
@@ -697,17 +699,24 @@ next_tx_int:
 
 static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
                                         struct bnxt_rx_ring_info *rxr,
+                                        unsigned int *offset,
                                         gfp_t gfp)
 {
        struct device *dev = &bp->pdev->dev;
        struct page *page;
 
-       page = page_pool_dev_alloc_pages(rxr->page_pool);
+       if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) {
+               page = page_pool_dev_alloc_frag(rxr->page_pool, offset,
+                                               BNXT_RX_PAGE_SIZE);
+       } else {
+               page = page_pool_dev_alloc_pages(rxr->page_pool);
+               *offset = 0;
+       }
        if (!page)
                return NULL;
 
-       *mapping = dma_map_page_attrs(dev, page, 0, PAGE_SIZE, bp->rx_dir,
-                                     DMA_ATTR_WEAK_ORDERING);
+       *mapping = dma_map_page_attrs(dev, page, *offset, BNXT_RX_PAGE_SIZE,
+                                     bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
        if (dma_mapping_error(dev, *mapping)) {
                page_pool_recycle_direct(rxr->page_pool, page);
                return NULL;
@@ -747,15 +756,16 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
        dma_addr_t mapping;
 
        if (BNXT_RX_PAGE_MODE(bp)) {
+               unsigned int offset;
                struct page *page =
-                       __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp);
+                       __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp);
 
                if (!page)
                        return -ENOMEM;
 
                mapping += bp->rx_dma_offset;
                rx_buf->data = page;
-               rx_buf->data_ptr = page_address(page) + bp->rx_offset;
+               rx_buf->data_ptr = page_address(page) + offset + bp->rx_offset;
        } else {
                u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, gfp);
 
@@ -815,7 +825,7 @@ static inline int bnxt_alloc_rx_page(struct bnxt *bp,
        unsigned int offset = 0;
 
        if (BNXT_RX_PAGE_MODE(bp)) {
-               page = __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp);
+               page = __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp);
 
                if (!page)
                        return -ENOMEM;
@@ -962,15 +972,15 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp,
                return NULL;
        }
        dma_addr -= bp->rx_dma_offset;
-       dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir,
-                            DMA_ATTR_WEAK_ORDERING);
-       skb = build_skb(page_address(page), PAGE_SIZE);
+       dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
+                            bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
+       skb = build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE);
        if (!skb) {
                page_pool_recycle_direct(rxr->page_pool, page);
                return NULL;
        }
        skb_mark_for_recycle(skb);
-       skb_reserve(skb, bp->rx_dma_offset);
+       skb_reserve(skb, bp->rx_offset);
        __skb_put(skb, len);
 
        return skb;
@@ -996,8 +1006,8 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
                return NULL;
        }
        dma_addr -= bp->rx_dma_offset;
-       dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir,
-                            DMA_ATTR_WEAK_ORDERING);
+       dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
+                            bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
 
        if (unlikely(!payload))
                payload = eth_get_headlen(bp->dev, data_ptr, len);
@@ -1010,7 +1020,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
 
        skb_mark_for_recycle(skb);
        off = (void *)data_ptr - page_address(page);
-       skb_add_rx_frag(skb, 0, page, off, len, PAGE_SIZE);
+       skb_add_rx_frag(skb, 0, page, off, len, BNXT_RX_PAGE_SIZE);
        memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN,
               payload + NET_IP_ALIGN);
 
@@ -1141,7 +1151,7 @@ static struct sk_buff *bnxt_rx_agg_pages_skb(struct bnxt *bp,
 
        skb->data_len += total_frag_len;
        skb->len += total_frag_len;
-       skb->truesize += PAGE_SIZE * agg_bufs;
+       skb->truesize += BNXT_RX_PAGE_SIZE * agg_bufs;
        return skb;
 }
 
@@ -2569,12 +2579,11 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
        return rx_pkts;
 }
 
-static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
+static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi,
+                                 int budget)
 {
-       if (bnapi->tx_pkts) {
-               bnapi->tx_int(bp, bnapi, bnapi->tx_pkts);
-               bnapi->tx_pkts = 0;
-       }
+       if (bnapi->tx_pkts)
+               bnapi->tx_int(bp, bnapi, budget);
 
        if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) {
                struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
@@ -2603,7 +2612,7 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
         */
        bnxt_db_cq(bp, &cpr->cp_db, cpr->cp_raw_cons);
 
-       __bnxt_poll_work_done(bp, bnapi);
+       __bnxt_poll_work_done(bp, bnapi, budget);
        return rx_pkts;
 }
 
@@ -2734,7 +2743,7 @@ static int __bnxt_poll_cqs(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
 }
 
 static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
-                                u64 dbr_type)
+                                u64 dbr_type, int budget)
 {
        struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
        int i;
@@ -2750,7 +2759,7 @@ static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
                        cpr2->had_work_done = 0;
                }
        }
-       __bnxt_poll_work_done(bp, bnapi);
+       __bnxt_poll_work_done(bp, bnapi, budget);
 }
 
 static int bnxt_poll_p5(struct napi_struct *napi, int budget)
@@ -2780,7 +2789,8 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
                        if (cpr->has_more_work)
                                break;
 
-                       __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL);
+                       __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL,
+                                            budget);
                        cpr->cp_raw_cons = raw_cons;
                        if (napi_complete_done(napi, work_done))
                                BNXT_DB_NQ_ARM_P5(&cpr->cp_db,
@@ -2810,7 +2820,7 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
                }
                raw_cons = NEXT_RAW_CMP(raw_cons);
        }
-       __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ);
+       __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ, budget);
        if (raw_cons != cpr->cp_raw_cons) {
                cpr->cp_raw_cons = raw_cons;
                BNXT_DB_NQ_P5(&cpr->cp_db, raw_cons);
@@ -2943,8 +2953,8 @@ skip_rx_tpa_free:
                rx_buf->data = NULL;
                if (BNXT_RX_PAGE_MODE(bp)) {
                        mapping -= bp->rx_dma_offset;
-                       dma_unmap_page_attrs(&pdev->dev, mapping, PAGE_SIZE,
-                                            bp->rx_dir,
+                       dma_unmap_page_attrs(&pdev->dev, mapping,
+                                            BNXT_RX_PAGE_SIZE, bp->rx_dir,
                                             DMA_ATTR_WEAK_ORDERING);
                        page_pool_recycle_direct(rxr->page_pool, data);
                } else {
@@ -3213,6 +3223,8 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
        pp.napi = &rxr->bnapi->napi;
        pp.dev = &bp->pdev->dev;
        pp.dma_dir = DMA_BIDIRECTIONAL;
+       if (PAGE_SIZE > BNXT_RX_PAGE_SIZE)
+               pp.flags |= PP_FLAG_PAGE_FRAG;
 
        rxr->page_pool = page_pool_create(&pp);
        if (IS_ERR(rxr->page_pool)) {
@@ -3989,26 +4001,29 @@ void bnxt_set_ring_params(struct bnxt *bp)
  */
 int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
 {
+       struct net_device *dev = bp->dev;
+
        if (page_mode) {
                bp->flags &= ~BNXT_FLAG_AGG_RINGS;
                bp->flags |= BNXT_FLAG_RX_PAGE_MODE;
 
-               if (bp->dev->mtu > BNXT_MAX_PAGE_MODE_MTU) {
+               if (bp->xdp_prog->aux->xdp_has_frags)
+                       dev->max_mtu = min_t(u16, bp->max_mtu, BNXT_MAX_MTU);
+               else
+                       dev->max_mtu =
+                               min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU);
+               if (dev->mtu > BNXT_MAX_PAGE_MODE_MTU) {
                        bp->flags |= BNXT_FLAG_JUMBO;
                        bp->rx_skb_func = bnxt_rx_multi_page_skb;
-                       bp->dev->max_mtu =
-                               min_t(u16, bp->max_mtu, BNXT_MAX_MTU);
                } else {
                        bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
                        bp->rx_skb_func = bnxt_rx_page_skb;
-                       bp->dev->max_mtu =
-                               min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU);
                }
                bp->rx_dir = DMA_BIDIRECTIONAL;
                /* Disable LRO or GRO_HW */
-               netdev_update_features(bp->dev);
+               netdev_update_features(dev);
        } else {
-               bp->dev->max_mtu = bp->max_mtu;
+               dev->max_mtu = bp->max_mtu;
                bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE;
                bp->rx_dir = DMA_FROM_DEVICE;
                bp->rx_skb_func = bnxt_rx_skb;
@@ -9429,6 +9444,8 @@ static void bnxt_enable_napi(struct bnxt *bp)
                        cpr->sw_stats.rx.rx_resets++;
                bnapi->in_reset = false;
 
+               bnapi->tx_pkts = 0;
+
                if (bnapi->rx_ring) {
                        INIT_WORK(&cpr->dim.work, bnxt_dim_work);
                        cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
index 080e73496066b617350740e583071a8f762acd1d..bb95c3dc5270f6641d07c3fc549299eaf61e0b06 100644 (file)
@@ -1005,7 +1005,7 @@ struct bnxt_napi {
        struct bnxt_tx_ring_info        *tx_ring;
 
        void                    (*tx_int)(struct bnxt *, struct bnxt_napi *,
-                                         int);
+                                         int budget);
        int                     tx_pkts;
        u8                      events;
 
index 4efa5fe6972b2ffab2cf82cbd4fe35a827c1e3b5..fb43232310b2dddd8c7aa38c0657ee47a572a91a 100644 (file)
@@ -125,16 +125,20 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp,
        dma_unmap_len_set(tx_buf, len, 0);
 }
 
-void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
 {
        struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
        struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
        bool rx_doorbell_needed = false;
+       int nr_pkts = bnapi->tx_pkts;
        struct bnxt_sw_tx_bd *tx_buf;
        u16 tx_cons = txr->tx_cons;
        u16 last_tx_cons = tx_cons;
        int i, j, frags;
 
+       if (!budget)
+               return;
+
        for (i = 0; i < nr_pkts; i++) {
                tx_buf = &txr->tx_buf_ring[tx_cons];
 
@@ -161,6 +165,8 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
                }
                tx_cons = NEXT_TX(tx_cons);
        }
+
+       bnapi->tx_pkts = 0;
        WRITE_ONCE(txr->tx_cons, tx_cons);
        if (rx_doorbell_needed) {
                tx_buf = &txr->tx_buf_ring[last_tx_cons];
@@ -180,8 +186,8 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
                        u16 cons, u8 *data_ptr, unsigned int len,
                        struct xdp_buff *xdp)
 {
+       u32 buflen = BNXT_RX_PAGE_SIZE;
        struct bnxt_sw_rx_bd *rx_buf;
-       u32 buflen = PAGE_SIZE;
        struct pci_dev *pdev;
        dma_addr_t mapping;
        u32 offset;
@@ -297,7 +303,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
                rx_buf = &rxr->rx_buf_ring[cons];
                mapping = rx_buf->mapping - bp->rx_dma_offset;
                dma_unmap_page_attrs(&pdev->dev, mapping,
-                                    PAGE_SIZE, bp->rx_dir,
+                                    BNXT_RX_PAGE_SIZE, bp->rx_dir,
                                     DMA_ATTR_WEAK_ORDERING);
 
                /* if we are unable to allocate a new buffer, abort and reuse */
@@ -480,7 +486,7 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
        }
        xdp_update_skb_shared_info(skb, num_frags,
                                   sinfo->xdp_frags_size,
-                                  PAGE_SIZE * sinfo->nr_frags,
+                                  BNXT_RX_PAGE_SIZE * sinfo->nr_frags,
                                   xdp_buff_is_frag_pfmemalloc(xdp));
        return skb;
 }
index ea430d6961df32abba20ac867fa0acf44fec9233..5e412c5655ba56fd7066803ff7f3071b322036be 100644 (file)
@@ -16,7 +16,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
                                   struct bnxt_tx_ring_info *txr,
                                   dma_addr_t mapping, u32 len,
                                   struct xdp_buff *xdp);
-void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts);
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget);
 bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
                 struct xdp_buff xdp, struct page *page, u8 **data_ptr,
                 unsigned int *len, u8 *event);
index f6a0f12a6d520f7c20eae01b6c39cc64faf22553..82929ee76739de4eb435520c2ceb42050ae950be 100644 (file)
@@ -5194,6 +5194,9 @@ static int __maybe_unused macb_suspend(struct device *dev)
        unsigned int q;
        int err;
 
+       if (!device_may_wakeup(&bp->dev->dev))
+               phy_exit(bp->sgmii_phy);
+
        if (!netif_running(netdev))
                return 0;
 
@@ -5254,7 +5257,6 @@ static int __maybe_unused macb_suspend(struct device *dev)
        if (!(bp->wol & MACB_WOL_ENABLED)) {
                rtnl_lock();
                phylink_stop(bp->phylink);
-               phy_exit(bp->sgmii_phy);
                rtnl_unlock();
                spin_lock_irqsave(&bp->lock, flags);
                macb_reset_hw(bp);
@@ -5284,6 +5286,9 @@ static int __maybe_unused macb_resume(struct device *dev)
        unsigned int q;
        int err;
 
+       if (!device_may_wakeup(&bp->dev->dev))
+               phy_init(bp->sgmii_phy);
+
        if (!netif_running(netdev))
                return 0;
 
@@ -5344,8 +5349,6 @@ static int __maybe_unused macb_resume(struct device *dev)
        macb_set_rx_mode(netdev);
        macb_restore_features(bp);
        rtnl_lock();
-       if (!device_may_wakeup(&bp->dev->dev))
-               phy_init(bp->sgmii_phy);
 
        phylink_start(bp->phylink);
        rtnl_unlock();
index 1416262d42967aea34ad5e0213505f21c9f0227a..e0a4cb7e3f501732ea1001fb96474dfb57590718 100644 (file)
@@ -1186,14 +1186,9 @@ static int enetc_init_port_rss_memory(struct enetc_si *si)
 
 static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
 {
-       struct device_node *node = pdev->dev.of_node;
        struct platform_device *ierb_pdev;
        struct device_node *ierb_node;
 
-       /* Don't register with the IERB if the PF itself is disabled */
-       if (!node || !of_device_is_available(node))
-               return 0;
-
        ierb_node = of_find_compatible_node(NULL, NULL,
                                            "fsl,ls1028a-enetc-ierb");
        if (!ierb_node || !of_device_is_available(ierb_node))
@@ -1208,56 +1203,81 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
        return enetc_ierb_register_pf(ierb_pdev, pdev);
 }
 
-static int enetc_pf_probe(struct pci_dev *pdev,
-                         const struct pci_device_id *ent)
+static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 {
-       struct device_node *node = pdev->dev.of_node;
-       struct enetc_ndev_priv *priv;
-       struct net_device *ndev;
        struct enetc_si *si;
-       struct enetc_pf *pf;
        int err;
 
-       err = enetc_pf_register_with_ierb(pdev);
-       if (err == -EPROBE_DEFER)
-               return err;
-       if (err)
-               dev_warn(&pdev->dev,
-                        "Could not register with IERB driver: %pe, please update the device tree\n",
-                        ERR_PTR(err));
-
-       err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
-       if (err)
-               return dev_err_probe(&pdev->dev, err, "PCI probing failed\n");
+       err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(struct enetc_pf));
+       if (err) {
+               dev_err_probe(&pdev->dev, err, "PCI probing failed\n");
+               goto out;
+       }
 
        si = pci_get_drvdata(pdev);
        if (!si->hw.port || !si->hw.global) {
                err = -ENODEV;
                dev_err(&pdev->dev, "could not map PF space, probing a VF?\n");
-               goto err_map_pf_space;
+               goto out_pci_remove;
        }
 
        err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,
                               &si->cbd_ring);
        if (err)
-               goto err_setup_cbdr;
+               goto out_pci_remove;
 
        err = enetc_init_port_rfs_memory(si);
        if (err) {
                dev_err(&pdev->dev, "Failed to initialize RFS memory\n");
-               goto err_init_port_rfs;
+               goto out_teardown_cbdr;
        }
 
        err = enetc_init_port_rss_memory(si);
        if (err) {
                dev_err(&pdev->dev, "Failed to initialize RSS memory\n");
-               goto err_init_port_rss;
+               goto out_teardown_cbdr;
        }
 
-       if (node && !of_device_is_available(node)) {
-               dev_info(&pdev->dev, "device is disabled, skipping\n");
-               err = -ENODEV;
-               goto err_device_disabled;
+       return si;
+
+out_teardown_cbdr:
+       enetc_teardown_cbdr(&si->cbd_ring);
+out_pci_remove:
+       enetc_pci_remove(pdev);
+out:
+       return ERR_PTR(err);
+}
+
+static void enetc_psi_destroy(struct pci_dev *pdev)
+{
+       struct enetc_si *si = pci_get_drvdata(pdev);
+
+       enetc_teardown_cbdr(&si->cbd_ring);
+       enetc_pci_remove(pdev);
+}
+
+static int enetc_pf_probe(struct pci_dev *pdev,
+                         const struct pci_device_id *ent)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct enetc_ndev_priv *priv;
+       struct net_device *ndev;
+       struct enetc_si *si;
+       struct enetc_pf *pf;
+       int err;
+
+       err = enetc_pf_register_with_ierb(pdev);
+       if (err == -EPROBE_DEFER)
+               return err;
+       if (err)
+               dev_warn(&pdev->dev,
+                        "Could not register with IERB driver: %pe, please update the device tree\n",
+                        ERR_PTR(err));
+
+       si = enetc_psi_create(pdev);
+       if (IS_ERR(si)) {
+               err = PTR_ERR(si);
+               goto err_psi_create;
        }
 
        pf = enetc_si_priv(si);
@@ -1339,15 +1359,9 @@ err_alloc_si_res:
        si->ndev = NULL;
        free_netdev(ndev);
 err_alloc_netdev:
-err_init_port_rss:
-err_init_port_rfs:
-err_device_disabled:
 err_setup_mac_addresses:
-       enetc_teardown_cbdr(&si->cbd_ring);
-err_setup_cbdr:
-err_map_pf_space:
-       enetc_pci_remove(pdev);
-
+       enetc_psi_destroy(pdev);
+err_psi_create:
        return err;
 }
 
@@ -1370,12 +1384,29 @@ static void enetc_pf_remove(struct pci_dev *pdev)
        enetc_free_msix(priv);
 
        enetc_free_si_resources(priv);
-       enetc_teardown_cbdr(&si->cbd_ring);
 
        free_netdev(si->ndev);
 
-       enetc_pci_remove(pdev);
+       enetc_psi_destroy(pdev);
+}
+
+static void enetc_fixup_clear_rss_rfs(struct pci_dev *pdev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct enetc_si *si;
+
+       /* Only apply quirk for disabled functions. For the ones
+        * that are enabled, enetc_pf_probe() will apply it.
+        */
+       if (node && of_device_is_available(node))
+               return;
+
+       si = enetc_psi_create(pdev);
+       if (si)
+               enetc_psi_destroy(pdev);
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF,
+                       enetc_fixup_clear_rss_rfs);
 
 static const struct pci_device_id enetc_pf_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) },
index 52546f625c8b0b9e6fa42f84a2de4beea6558adb..f276b5ecb431fc7adade443d122cb5c13a3c53f3 100644 (file)
@@ -464,9 +464,9 @@ static void hns3_dbg_fill_content(char *content, u16 len,
                if (result) {
                        if (item_len < strlen(result[i]))
                                break;
-                       strscpy(pos, result[i], strlen(result[i]));
+                       memcpy(pos, result[i], strlen(result[i]));
                } else {
-                       strscpy(pos, items[i].name, strlen(items[i].name));
+                       memcpy(pos, items[i].name, strlen(items[i].name));
                }
                pos += item_len;
                len -= item_len;
index 9f6890059666e50bde32445c801369417c882796..b7b51e56b0308b016e7d49ad6a17daaf90dd3b67 100644 (file)
@@ -5854,6 +5854,9 @@ void hns3_external_lb_prepare(struct net_device *ndev, bool if_running)
        if (!if_running)
                return;
 
+       if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state))
+               return;
+
        netif_carrier_off(ndev);
        netif_tx_disable(ndev);
 
@@ -5882,7 +5885,16 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running)
        if (!if_running)
                return;
 
-       hns3_nic_reset_all_ring(priv->ae_handle);
+       if (hns3_nic_resetting(ndev))
+               return;
+
+       if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
+               return;
+
+       if (hns3_nic_reset_all_ring(priv->ae_handle))
+               return;
+
+       clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
 
        for (i = 0; i < priv->vector_num; i++)
                hns3_vector_enable(&priv->tqp_vector[i]);
index 409db2e70965185e62da44705c4c6aead502a8fa..0fb2eaee3e8a0a8bcfd193a3f02dd86b11b92ff8 100644 (file)
@@ -111,9 +111,9 @@ static void hclge_dbg_fill_content(char *content, u16 len,
                if (result) {
                        if (item_len < strlen(result[i]))
                                break;
-                       strscpy(pos, result[i], strlen(result[i]));
+                       memcpy(pos, result[i], strlen(result[i]));
                } else {
-                       strscpy(pos, items[i].name, strlen(items[i].name));
+                       memcpy(pos, items[i].name, strlen(items[i].name));
                }
                pos += item_len;
                len -= item_len;
index bf675c15fbb9c9093dfc20b6046f268a32f12055..a940e35aef29d190b7c90f1cbeed9c37d5d9590d 100644 (file)
@@ -72,6 +72,8 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev);
 static void hclge_sync_promisc_mode(struct hclge_dev *hdev);
 static void hclge_sync_fd_table(struct hclge_dev *hdev);
 static void hclge_update_fec_stats(struct hclge_dev *hdev);
+static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret,
+                                     int wait_cnt);
 
 static struct hnae3_ae_algo ae_algo;
 
@@ -7558,6 +7560,8 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable)
 
 static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
 {
+#define HCLGE_LINK_STATUS_WAIT_CNT  3
+
        struct hclge_desc desc;
        struct hclge_config_mac_mode_cmd *req =
                (struct hclge_config_mac_mode_cmd *)desc.data;
@@ -7582,9 +7586,15 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
        req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en);
 
        ret = hclge_cmd_send(&hdev->hw, &desc, 1);
-       if (ret)
+       if (ret) {
                dev_err(&hdev->pdev->dev,
                        "mac enable fail, ret =%d.\n", ret);
+               return;
+       }
+
+       if (!enable)
+               hclge_mac_link_status_wait(hdev, HCLGE_LINK_STATUS_DOWN,
+                                          HCLGE_LINK_STATUS_WAIT_CNT);
 }
 
 static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid,
@@ -7647,10 +7657,9 @@ static void hclge_phy_link_status_wait(struct hclge_dev *hdev,
        } while (++i < HCLGE_PHY_LINK_STATUS_NUM);
 }
 
-static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
+static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret,
+                                     int wait_cnt)
 {
-#define HCLGE_MAC_LINK_STATUS_NUM  100
-
        int link_status;
        int i = 0;
        int ret;
@@ -7663,13 +7672,15 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
                        return 0;
 
                msleep(HCLGE_LINK_STATUS_MS);
-       } while (++i < HCLGE_MAC_LINK_STATUS_NUM);
+       } while (++i < wait_cnt);
        return -EBUSY;
 }
 
 static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
                                          bool is_phy)
 {
+#define HCLGE_MAC_LINK_STATUS_NUM  100
+
        int link_ret;
 
        link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN;
@@ -7677,7 +7688,8 @@ static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
        if (is_phy)
                hclge_phy_link_status_wait(hdev, link_ret);
 
-       return hclge_mac_link_status_wait(hdev, link_ret);
+       return hclge_mac_link_status_wait(hdev, link_ret,
+                                         HCLGE_MAC_LINK_STATUS_NUM);
 }
 
 static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en)
@@ -10915,9 +10927,12 @@ int hclge_cfg_flowctrl(struct hclge_dev *hdev)
        u32 rx_pause, tx_pause;
        u8 flowctl;
 
-       if (!phydev->link || !phydev->autoneg)
+       if (!phydev->link)
                return 0;
 
+       if (!phydev->autoneg)
+               return hclge_mac_pause_setup_hw(hdev);
+
        local_advertising = linkmode_adv_to_lcl_adv_t(phydev->advertising);
 
        if (phydev->pause)
index de509e5751a7c5105b06452e5e892e3025241005..c58c3122176289cb0991e45e823f74ad3bf83e3a 100644 (file)
@@ -1553,7 +1553,7 @@ static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc)
        return 0;
 }
 
-static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
+int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
 {
        bool tx_en, rx_en;
 
index 45dcfef3f90cca95072835bf975afb96250c6b08..53eec6df5194682da957a0a2f57a161df87fc953 100644 (file)
@@ -245,6 +245,7 @@ int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
                           u8 pfc_bitmap);
 int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
 int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr);
+int hclge_mac_pause_setup_hw(struct hclge_dev *hdev);
 void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
 void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats);
 int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate);
index 763d613adbcc0ecbcd5bc6a183f89b9671d3a2d8..df76cdaddcfb0976a4ba5b4d5ea07e8097387765 100644 (file)
@@ -97,6 +97,8 @@ static int pending_scrq(struct ibmvnic_adapter *,
 static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *,
                                        struct ibmvnic_sub_crq_queue *);
 static int ibmvnic_poll(struct napi_struct *napi, int data);
+static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter);
+static inline void reinit_init_done(struct ibmvnic_adapter *adapter);
 static void send_query_map(struct ibmvnic_adapter *adapter);
 static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, u32, u8);
 static int send_request_unmap(struct ibmvnic_adapter *, u8);
@@ -114,6 +116,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
 static void free_long_term_buff(struct ibmvnic_adapter *adapter,
                                struct ibmvnic_long_term_buff *ltb);
 static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter);
+static void flush_reset_queue(struct ibmvnic_adapter *adapter);
 
 struct ibmvnic_stat {
        char name[ETH_GSTRING_LEN];
@@ -1505,8 +1508,8 @@ static const char *adapter_state_to_string(enum vnic_state state)
 
 static int ibmvnic_login(struct net_device *netdev)
 {
+       unsigned long flags, timeout = msecs_to_jiffies(20000);
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
-       unsigned long timeout = msecs_to_jiffies(20000);
        int retry_count = 0;
        int retries = 10;
        bool retry;
@@ -1527,11 +1530,9 @@ static int ibmvnic_login(struct net_device *netdev)
 
                if (!wait_for_completion_timeout(&adapter->init_done,
                                                 timeout)) {
-                       netdev_warn(netdev, "Login timed out, retrying...\n");
-                       retry = true;
-                       adapter->init_done_rc = 0;
-                       retry_count++;
-                       continue;
+                       netdev_warn(netdev, "Login timed out\n");
+                       adapter->login_pending = false;
+                       goto partial_reset;
                }
 
                if (adapter->init_done_rc == ABORTED) {
@@ -1573,10 +1574,69 @@ static int ibmvnic_login(struct net_device *netdev)
                                            "SCRQ irq initialization failed\n");
                                return rc;
                        }
+               /* Default/timeout error handling, reset and start fresh */
                } else if (adapter->init_done_rc) {
                        netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n",
                                    adapter->init_done_rc);
-                       return -EIO;
+
+partial_reset:
+                       /* adapter login failed, so free any CRQs or sub-CRQs
+                        * and register again before attempting to login again.
+                        * If we don't do this then the VIOS may think that
+                        * we are already logged in and reject any subsequent
+                        * attempts
+                        */
+                       netdev_warn(netdev,
+                                   "Freeing and re-registering CRQs before attempting to login again\n");
+                       retry = true;
+                       adapter->init_done_rc = 0;
+                       release_sub_crqs(adapter, true);
+                       /* Much of this is similar logic as ibmvnic_probe(),
+                        * we are essentially re-initializing communication
+                        * with the server. We really should not run any
+                        * resets/failovers here because this is already a form
+                        * of reset and we do not want parallel resets occurring
+                        */
+                       do {
+                               reinit_init_done(adapter);
+                               /* Clear any failovers we got in the previous
+                                * pass since we are re-initializing the CRQ
+                                */
+                               adapter->failover_pending = false;
+                               release_crq_queue(adapter);
+                               /* If we don't sleep here then we risk an
+                                * unnecessary failover event from the VIOS.
+                                * This is a known VIOS issue caused by a vnic
+                                * device freeing and registering a CRQ too
+                                * quickly.
+                                */
+                               msleep(1500);
+                               /* Avoid any resets, since we are currently
+                                * resetting.
+                                */
+                               spin_lock_irqsave(&adapter->rwi_lock, flags);
+                               flush_reset_queue(adapter);
+                               spin_unlock_irqrestore(&adapter->rwi_lock,
+                                                      flags);
+
+                               rc = init_crq_queue(adapter);
+                               if (rc) {
+                                       netdev_err(netdev, "login recovery: init CRQ failed %d\n",
+                                                  rc);
+                                       return -EIO;
+                               }
+
+                               rc = ibmvnic_reset_init(adapter, false);
+                               if (rc)
+                                       netdev_err(netdev, "login recovery: Reset init failed %d\n",
+                                                  rc);
+                               /* IBMVNIC_CRQ_INIT will return EAGAIN if it
+                                * fails, since ibmvnic_reset_init will free
+                                * irq's in failure, we won't be able to receive
+                                * new CRQs so we need to keep trying. probe()
+                                * handles this similarly.
+                                */
+                       } while (rc == -EAGAIN && retry_count++ < retries);
                }
        } while (retry);
 
@@ -1588,12 +1648,22 @@ static int ibmvnic_login(struct net_device *netdev)
 
 static void release_login_buffer(struct ibmvnic_adapter *adapter)
 {
+       if (!adapter->login_buf)
+               return;
+
+       dma_unmap_single(&adapter->vdev->dev, adapter->login_buf_token,
+                        adapter->login_buf_sz, DMA_TO_DEVICE);
        kfree(adapter->login_buf);
        adapter->login_buf = NULL;
 }
 
 static void release_login_rsp_buffer(struct ibmvnic_adapter *adapter)
 {
+       if (!adapter->login_rsp_buf)
+               return;
+
+       dma_unmap_single(&adapter->vdev->dev, adapter->login_rsp_buf_token,
+                        adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
        kfree(adapter->login_rsp_buf);
        adapter->login_rsp_buf = NULL;
 }
@@ -4830,11 +4900,14 @@ static int send_login(struct ibmvnic_adapter *adapter)
        if (rc) {
                adapter->login_pending = false;
                netdev_err(adapter->netdev, "Failed to send login, rc=%d\n", rc);
-               goto buf_rsp_map_failed;
+               goto buf_send_failed;
        }
 
        return 0;
 
+buf_send_failed:
+       dma_unmap_single(dev, rsp_buffer_token, rsp_buffer_size,
+                        DMA_FROM_DEVICE);
 buf_rsp_map_failed:
        kfree(login_rsp_buffer);
        adapter->login_rsp_buf = NULL;
@@ -5396,6 +5469,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
        int num_tx_pools;
        int num_rx_pools;
        u64 *size_array;
+       u32 rsp_len;
        int i;
 
        /* CHECK: Test/set of login_pending does not need to be atomic
@@ -5407,11 +5481,6 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
        }
        adapter->login_pending = false;
 
-       dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz,
-                        DMA_TO_DEVICE);
-       dma_unmap_single(dev, adapter->login_rsp_buf_token,
-                        adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
-
        /* If the number of queues requested can't be allocated by the
         * server, the login response will return with code 1. We will need
         * to resend the login buffer with fewer queues requested.
@@ -5447,6 +5516,23 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
                ibmvnic_reset(adapter, VNIC_RESET_FATAL);
                return -EIO;
        }
+
+       rsp_len = be32_to_cpu(login_rsp->len);
+       if (be32_to_cpu(login->login_rsp_len) < rsp_len ||
+           rsp_len <= be32_to_cpu(login_rsp->off_txsubm_subcrqs) ||
+           rsp_len <= be32_to_cpu(login_rsp->off_rxadd_subcrqs) ||
+           rsp_len <= be32_to_cpu(login_rsp->off_rxadd_buff_size) ||
+           rsp_len <= be32_to_cpu(login_rsp->off_supp_tx_desc)) {
+               /* This can happen if a login request times out and there are
+                * 2 outstanding login requests sent, the LOGIN_RSP crq
+                * could have been for the older login request. So we are
+                * parsing the newer response buffer which may be incomplete
+                */
+               dev_err(dev, "FATAL: Login rsp offsets/lengths invalid\n");
+               ibmvnic_reset(adapter, VNIC_RESET_FATAL);
+               return -EIO;
+       }
+
        size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
                be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size));
        /* variable buffer sizes are not supported, so just read the
index 9da0c87f03288719b5b08869e01d976c5cc72a53..f99c1f7fec406dd286d637249a68212ba1ee32ff 100644 (file)
@@ -210,11 +210,11 @@ read_nvm_exit:
  * @hw: pointer to the HW structure.
  * @module_pointer: module pointer location in words from the NVM beginning
  * @offset: offset in words from module start
- * @words: number of words to write
- * @data: buffer with words to write to the Shadow RAM
+ * @words: number of words to read
+ * @data: buffer with words to read to the Shadow RAM
  * @last_command: tells the AdminQ that this is the last command
  *
- * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
+ * Reads a 16 bit words buffer to the Shadow RAM using the admin command.
  **/
 static int i40e_read_nvm_aq(struct i40e_hw *hw,
                            u8 module_pointer, u32 offset,
@@ -234,18 +234,18 @@ static int i40e_read_nvm_aq(struct i40e_hw *hw,
         */
        if ((offset + words) > hw->nvm.sr_size)
                i40e_debug(hw, I40E_DEBUG_NVM,
-                          "NVM write error: offset %d beyond Shadow RAM limit %d\n",
+                          "NVM read error: offset %d beyond Shadow RAM limit %d\n",
                           (offset + words), hw->nvm.sr_size);
        else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
-               /* We can write only up to 4KB (one sector), in one AQ write */
+               /* We can read only up to 4KB (one sector), in one AQ write */
                i40e_debug(hw, I40E_DEBUG_NVM,
-                          "NVM write fail error: tried to write %d words, limit is %d.\n",
+                          "NVM read fail error: tried to read %d words, limit is %d.\n",
                           words, I40E_SR_SECTOR_SIZE_IN_WORDS);
        else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
                 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
-               /* A single write cannot spread over two sectors */
+               /* A single read cannot spread over two sectors */
                i40e_debug(hw, I40E_DEBUG_NVM,
-                          "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
+                          "NVM read error: cannot spread over two sectors in a single read offset=%d words=%d\n",
                           offset, words);
        else
                ret_code = i40e_aq_read_nvm(hw, module_pointer,
index 2f47cfa7f06e20350f140154b6160c8bbcff8b83..a34303ad057d005c7289ec161562ed916b5d7827 100644 (file)
@@ -1289,6 +1289,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
                fltr->ip_mask.src_port = fsp->m_u.tcp_ip4_spec.psrc;
                fltr->ip_mask.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
                fltr->ip_mask.tos = fsp->m_u.tcp_ip4_spec.tos;
+               fltr->ip_ver = 4;
                break;
        case AH_V4_FLOW:
        case ESP_V4_FLOW:
@@ -1300,6 +1301,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
                fltr->ip_mask.v4_addrs.dst_ip = fsp->m_u.ah_ip4_spec.ip4dst;
                fltr->ip_mask.spi = fsp->m_u.ah_ip4_spec.spi;
                fltr->ip_mask.tos = fsp->m_u.ah_ip4_spec.tos;
+               fltr->ip_ver = 4;
                break;
        case IPV4_USER_FLOW:
                fltr->ip_data.v4_addrs.src_ip = fsp->h_u.usr_ip4_spec.ip4src;
@@ -1312,6 +1314,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
                fltr->ip_mask.l4_header = fsp->m_u.usr_ip4_spec.l4_4_bytes;
                fltr->ip_mask.tos = fsp->m_u.usr_ip4_spec.tos;
                fltr->ip_mask.proto = fsp->m_u.usr_ip4_spec.proto;
+               fltr->ip_ver = 4;
                break;
        case TCP_V6_FLOW:
        case UDP_V6_FLOW:
@@ -1330,6 +1333,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
                fltr->ip_mask.src_port = fsp->m_u.tcp_ip6_spec.psrc;
                fltr->ip_mask.dst_port = fsp->m_u.tcp_ip6_spec.pdst;
                fltr->ip_mask.tclass = fsp->m_u.tcp_ip6_spec.tclass;
+               fltr->ip_ver = 6;
                break;
        case AH_V6_FLOW:
        case ESP_V6_FLOW:
@@ -1345,6 +1349,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
                       sizeof(struct in6_addr));
                fltr->ip_mask.spi = fsp->m_u.ah_ip6_spec.spi;
                fltr->ip_mask.tclass = fsp->m_u.ah_ip6_spec.tclass;
+               fltr->ip_ver = 6;
                break;
        case IPV6_USER_FLOW:
                memcpy(&fltr->ip_data.v6_addrs.src_ip, fsp->h_u.usr_ip6_spec.ip6src,
@@ -1361,6 +1366,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
                fltr->ip_mask.l4_header = fsp->m_u.usr_ip6_spec.l4_4_bytes;
                fltr->ip_mask.tclass = fsp->m_u.usr_ip6_spec.tclass;
                fltr->ip_mask.proto = fsp->m_u.usr_ip6_spec.l4_proto;
+               fltr->ip_ver = 6;
                break;
        case ETHER_FLOW:
                fltr->eth_data.etype = fsp->h_u.ether_spec.h_proto;
@@ -1371,6 +1377,10 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
                return -EINVAL;
        }
 
+       err = iavf_validate_fdir_fltr_masks(adapter, fltr);
+       if (err)
+               return err;
+
        if (iavf_fdir_is_dup_fltr(adapter, fltr))
                return -EEXIST;
 
@@ -1401,14 +1411,15 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
        if (fsp->flow_type & FLOW_MAC_EXT)
                return -EINVAL;
 
+       spin_lock_bh(&adapter->fdir_fltr_lock);
        if (adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS) {
+               spin_unlock_bh(&adapter->fdir_fltr_lock);
                dev_err(&adapter->pdev->dev,
                        "Unable to add Flow Director filter because VF reached the limit of max allowed filters (%u)\n",
                        IAVF_MAX_FDIR_FILTERS);
                return -ENOSPC;
        }
 
-       spin_lock_bh(&adapter->fdir_fltr_lock);
        if (iavf_find_fdir_fltr_by_loc(adapter, fsp->location)) {
                dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n");
                spin_unlock_bh(&adapter->fdir_fltr_lock);
@@ -1781,7 +1792,9 @@ static int iavf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
        case ETHTOOL_GRXCLSRLCNT:
                if (!FDIR_FLTR_SUPPORT(adapter))
                        break;
+               spin_lock_bh(&adapter->fdir_fltr_lock);
                cmd->rule_cnt = adapter->fdir_active_fltr;
+               spin_unlock_bh(&adapter->fdir_fltr_lock);
                cmd->data = IAVF_MAX_FDIR_FILTERS;
                ret = 0;
                break;
index 6146203efd84ac18729383ee4211b41253d9a004..03e774bd2a5b43f9b90fe3a11e95254003983ccf 100644 (file)
@@ -18,6 +18,79 @@ static const struct in6_addr ipv6_addr_full_mask = {
        }
 };
 
+static const struct in6_addr ipv6_addr_zero_mask = {
+       .in6_u = {
+               .u6_addr8 = {
+                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               }
+       }
+};
+
+/**
+ * iavf_validate_fdir_fltr_masks - validate Flow Director filter fields masks
+ * @adapter: pointer to the VF adapter structure
+ * @fltr: Flow Director filter data structure
+ *
+ * Returns 0 if all masks of packet fields are either full or empty. Returns
+ * error on at least one partial mask.
+ */
+int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
+                                 struct iavf_fdir_fltr *fltr)
+{
+       if (fltr->eth_mask.etype && fltr->eth_mask.etype != htons(U16_MAX))
+               goto partial_mask;
+
+       if (fltr->ip_ver == 4) {
+               if (fltr->ip_mask.v4_addrs.src_ip &&
+                   fltr->ip_mask.v4_addrs.src_ip != htonl(U32_MAX))
+                       goto partial_mask;
+
+               if (fltr->ip_mask.v4_addrs.dst_ip &&
+                   fltr->ip_mask.v4_addrs.dst_ip != htonl(U32_MAX))
+                       goto partial_mask;
+
+               if (fltr->ip_mask.tos && fltr->ip_mask.tos != U8_MAX)
+                       goto partial_mask;
+       } else if (fltr->ip_ver == 6) {
+               if (memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_zero_mask,
+                          sizeof(struct in6_addr)) &&
+                   memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_full_mask,
+                          sizeof(struct in6_addr)))
+                       goto partial_mask;
+
+               if (memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_zero_mask,
+                          sizeof(struct in6_addr)) &&
+                   memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_full_mask,
+                          sizeof(struct in6_addr)))
+                       goto partial_mask;
+
+               if (fltr->ip_mask.tclass && fltr->ip_mask.tclass != U8_MAX)
+                       goto partial_mask;
+       }
+
+       if (fltr->ip_mask.proto && fltr->ip_mask.proto != U8_MAX)
+               goto partial_mask;
+
+       if (fltr->ip_mask.src_port && fltr->ip_mask.src_port != htons(U16_MAX))
+               goto partial_mask;
+
+       if (fltr->ip_mask.dst_port && fltr->ip_mask.dst_port != htons(U16_MAX))
+               goto partial_mask;
+
+       if (fltr->ip_mask.spi && fltr->ip_mask.spi != htonl(U32_MAX))
+               goto partial_mask;
+
+       if (fltr->ip_mask.l4_header &&
+           fltr->ip_mask.l4_header != htonl(U32_MAX))
+               goto partial_mask;
+
+       return 0;
+
+partial_mask:
+       dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, partial masks are not supported\n");
+       return -EOPNOTSUPP;
+}
+
 /**
  * iavf_pkt_udp_no_pay_len - the length of UDP packet without payload
  * @fltr: Flow Director filter data structure
@@ -263,8 +336,6 @@ iavf_fill_fdir_ip4_hdr(struct iavf_fdir_fltr *fltr,
                VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST);
        }
 
-       fltr->ip_ver = 4;
-
        return 0;
 }
 
@@ -309,8 +380,6 @@ iavf_fill_fdir_ip6_hdr(struct iavf_fdir_fltr *fltr,
                VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST);
        }
 
-       fltr->ip_ver = 6;
-
        return 0;
 }
 
@@ -722,7 +791,9 @@ void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *f
 bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
 {
        struct iavf_fdir_fltr *tmp;
+       bool ret = false;
 
+       spin_lock_bh(&adapter->fdir_fltr_lock);
        list_for_each_entry(tmp, &adapter->fdir_list_head, list) {
                if (tmp->flow_type != fltr->flow_type)
                        continue;
@@ -732,11 +803,14 @@ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *
                    !memcmp(&tmp->ip_data, &fltr->ip_data,
                            sizeof(fltr->ip_data)) &&
                    !memcmp(&tmp->ext_data, &fltr->ext_data,
-                           sizeof(fltr->ext_data)))
-                       return true;
+                           sizeof(fltr->ext_data))) {
+                       ret = true;
+                       break;
+               }
        }
+       spin_unlock_bh(&adapter->fdir_fltr_lock);
 
-       return false;
+       return ret;
 }
 
 /**
index 33c55c366315b2ca9d38edebd578e7b5d6dfc25e..9eb9f73f6adf3a52b42d0751032adff5fad9bcc0 100644 (file)
@@ -110,6 +110,8 @@ struct iavf_fdir_fltr {
        struct virtchnl_fdir_add vc_add_msg;
 };
 
+int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
+                                 struct iavf_fdir_fltr *fltr);
 int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
 void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
 bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
index ad0a007b739881d3220529b59fbc6171c093c46a..8f232c41a89e3b7f8a8ed6b34dced64931b99f07 100644 (file)
@@ -538,6 +538,12 @@ ice_eswitch_mode_set(struct devlink *devlink, u16 mode,
                break;
        case DEVLINK_ESWITCH_MODE_SWITCHDEV:
        {
+               if (ice_is_adq_active(pf)) {
+                       dev_err(ice_pf_to_dev(pf), "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root");
+                       NL_SET_ERR_MSG_MOD(extack, "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root");
+                       return -EOPNOTSUPP;
+               }
+
                dev_info(ice_pf_to_dev(pf), "PF %d changed eswitch mode to switchdev",
                         pf->hw.pf_id);
                NL_SET_ERR_MSG_MOD(extack, "Changed eswitch mode to switchdev");
index f02d44455772e584ff205559d33760631f59d4a6..b40dfe6ae3217a7cfd28529ea8483545af21b8ad 100644 (file)
@@ -8813,6 +8813,7 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type,
 {
        struct ice_netdev_priv *np = netdev_priv(netdev);
        struct ice_pf *pf = np->vsi->back;
+       bool locked = false;
        int err;
 
        switch (type) {
@@ -8822,10 +8823,32 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type,
                                                  ice_setup_tc_block_cb,
                                                  np, np, true);
        case TC_SETUP_QDISC_MQPRIO:
+               if (ice_is_eswitch_mode_switchdev(pf)) {
+                       netdev_err(netdev, "TC MQPRIO offload not supported, switchdev is enabled\n");
+                       return -EOPNOTSUPP;
+               }
+
+               if (pf->adev) {
+                       mutex_lock(&pf->adev_mutex);
+                       device_lock(&pf->adev->dev);
+                       locked = true;
+                       if (pf->adev->dev.driver) {
+                               netdev_err(netdev, "Cannot change qdisc when RDMA is active\n");
+                               err = -EBUSY;
+                               goto adev_unlock;
+                       }
+               }
+
                /* setup traffic classifier for receive side */
                mutex_lock(&pf->tc_mutex);
                err = ice_setup_tc_mqprio_qdisc(netdev, type_data);
                mutex_unlock(&pf->tc_mutex);
+
+adev_unlock:
+               if (locked) {
+                       device_unlock(&pf->adev->dev);
+                       mutex_unlock(&pf->adev_mutex);
+               }
                return err;
        default:
                return -EOPNOTSUPP;
index 9db384f66a8ee7245a02e2fae24ad4421c9a5605..38901d2a468074ab4da0dc63eea0a5128d03b257 100644 (file)
@@ -195,6 +195,10 @@ struct igc_adapter {
        u32 qbv_config_change_errors;
        bool qbv_transition;
        unsigned int qbv_count;
+       /* Access to oper_gate_closed, admin_gate_closed and qbv_transition
+        * are protected by the qbv_tx_lock.
+        */
+       spinlock_t qbv_tx_lock;
 
        /* OS defined structs */
        struct pci_dev *pdev;
index bdeb36790d774da5a2b86754fd7272061bbbd12b..6f557e843e49562e67134bbda16e5adf8b328c4c 100644 (file)
@@ -4801,6 +4801,7 @@ static int igc_sw_init(struct igc_adapter *adapter)
        adapter->nfc_rule_count = 0;
 
        spin_lock_init(&adapter->stats64_lock);
+       spin_lock_init(&adapter->qbv_tx_lock);
        /* Assume MSI-X interrupts, will be checked during IRQ allocation */
        adapter->flags |= IGC_FLAG_HAS_MSIX;
 
@@ -6119,15 +6120,15 @@ static int igc_tsn_enable_launchtime(struct igc_adapter *adapter,
        return igc_tsn_offload_apply(adapter);
 }
 
-static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
+static int igc_qbv_clear_schedule(struct igc_adapter *adapter)
 {
+       unsigned long flags;
        int i;
 
        adapter->base_time = 0;
        adapter->cycle_time = NSEC_PER_SEC;
        adapter->taprio_offload_enable = false;
        adapter->qbv_config_change_errors = 0;
-       adapter->qbv_transition = false;
        adapter->qbv_count = 0;
 
        for (i = 0; i < adapter->num_tx_queues; i++) {
@@ -6136,10 +6137,28 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
                ring->start_time = 0;
                ring->end_time = NSEC_PER_SEC;
                ring->max_sdu = 0;
+       }
+
+       spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
+
+       adapter->qbv_transition = false;
+
+       for (i = 0; i < adapter->num_tx_queues; i++) {
+               struct igc_ring *ring = adapter->tx_ring[i];
+
                ring->oper_gate_closed = false;
                ring->admin_gate_closed = false;
        }
 
+       spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
+
+       return 0;
+}
+
+static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
+{
+       igc_qbv_clear_schedule(adapter);
+
        return 0;
 }
 
@@ -6150,6 +6169,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
        struct igc_hw *hw = &adapter->hw;
        u32 start_time = 0, end_time = 0;
        struct timespec64 now;
+       unsigned long flags;
        size_t n;
        int i;
 
@@ -6217,6 +6237,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
                start_time += e->interval;
        }
 
+       spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
+
        /* Check whether a queue gets configured.
         * If not, set the start and end time to be end time.
         */
@@ -6241,6 +6263,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
                }
        }
 
+       spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
+
        for (i = 0; i < adapter->num_tx_queues; i++) {
                struct igc_ring *ring = adapter->tx_ring[i];
                struct net_device *dev = adapter->netdev;
@@ -6619,8 +6643,11 @@ static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer)
 {
        struct igc_adapter *adapter = container_of(timer, struct igc_adapter,
                                                   hrtimer);
+       unsigned long flags;
        unsigned int i;
 
+       spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
+
        adapter->qbv_transition = true;
        for (i = 0; i < adapter->num_tx_queues; i++) {
                struct igc_ring *tx_ring = adapter->tx_ring[i];
@@ -6633,6 +6660,9 @@ static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer)
                }
        }
        adapter->qbv_transition = false;
+
+       spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
+
        return HRTIMER_NORESTART;
 }
 
index 2b9335cb4bb3a1896643268bb1704d3091d08442..8537578e1cf1d4226150d508a714411ee0055f12 100644 (file)
@@ -1302,11 +1302,10 @@ static int korina_probe(struct platform_device *pdev)
        else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0)
                eth_hw_addr_random(dev);
 
-       clk = devm_clk_get_optional(&pdev->dev, "mdioclk");
+       clk = devm_clk_get_optional_enabled(&pdev->dev, "mdioclk");
        if (IS_ERR(clk))
                return PTR_ERR(clk);
        if (clk) {
-               clk_prepare_enable(clk);
                lp->mii_clock_freq = clk_get_rate(clk);
        } else {
                lp->mii_clock_freq = 200000000; /* max possible input clk */
index 035ead7935c741baafa11fe407baa8b620523dfb..dab61cc1acb5742e25ecd2ea70250088c2850bae 100644 (file)
@@ -98,6 +98,9 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
        writeq(OCTEP_CTRL_MBOX_STATUS_INIT,
               OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
 
+       mutex_init(&mbox->h2fq_lock);
+       mutex_init(&mbox->f2hq_lock);
+
        mbox->h2fq.sz = readl(OCTEP_CTRL_MBOX_H2FQ_SZ(mbox->barmem));
        mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD(mbox->barmem);
        mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS(mbox->barmem);
index 1cc6af2feb38afbdc6cc3bb67c8ea821ce3a8046..565320ec24f81e3fadd87460b5ab89ca4bdbcbd0 100644 (file)
@@ -55,7 +55,7 @@ static int octep_send_mbox_req(struct octep_device *oct,
        list_add_tail(&d->list, &oct->ctrl_req_wait_list);
        ret = wait_event_interruptible_timeout(oct->ctrl_req_wait_q,
                                               (d->done != 0),
-                                              jiffies + msecs_to_jiffies(500));
+                                              msecs_to_jiffies(500));
        list_del(&d->list);
        if (ret == 0 || ret == 1)
                return -EAGAIN;
index 43eb6e871351101f5f917ec90105f1202b21f50e..4424de2ffd70ca6762cfd1666ac326163bc9527e 100644 (file)
@@ -1038,6 +1038,10 @@ static void octep_device_cleanup(struct octep_device *oct)
 {
        int i;
 
+       oct->poll_non_ioq_intr = false;
+       cancel_delayed_work_sync(&oct->intr_poll_task);
+       cancel_work_sync(&oct->ctrl_mbox_task);
+
        dev_info(&oct->pdev->dev, "Cleaning up Octeon Device ...\n");
 
        for (i = 0; i < OCTEP_MAX_VF; i++) {
@@ -1200,14 +1204,11 @@ static void octep_remove(struct pci_dev *pdev)
        if (!oct)
                return;
 
-       cancel_work_sync(&oct->tx_timeout_task);
-       cancel_work_sync(&oct->ctrl_mbox_task);
        netdev = oct->netdev;
        if (netdev->reg_state == NETREG_REGISTERED)
                unregister_netdev(netdev);
 
-       oct->poll_non_ioq_intr = false;
-       cancel_delayed_work_sync(&oct->intr_poll_task);
+       cancel_work_sync(&oct->tx_timeout_task);
        octep_device_cleanup(oct);
        pci_release_mem_regions(pdev);
        free_netdev(netdev);
index f328d957b2db73bd3d9c3a42c0c6f0152cec5efe..35857dc19542f78418a0913a039a8bbe5609526a 100644 (file)
@@ -727,7 +727,8 @@ pick_fw_ver:
 
        err = request_firmware_direct(&fw->bin, fw_path, fw->dev.dev);
        if (err) {
-               if (ver_maj == PRESTERA_SUPP_FW_MAJ_VER) {
+               if (ver_maj != PRESTERA_PREV_FW_MAJ_VER ||
+                   ver_min != PRESTERA_PREV_FW_MIN_VER) {
                        ver_maj = PRESTERA_PREV_FW_MAJ_VER;
                        ver_min = PRESTERA_PREV_FW_MIN_VER;
 
index a9a1028cb17bbb736c0b0725acbf9ef2d3f7a166..de317179a7dcc7ef02ebd5d5d3fa1e7cbcd82c09 100644 (file)
@@ -166,11 +166,11 @@ prestera_util_neigh2nc_key(struct prestera_switch *sw, struct neighbour *n,
 
 static bool __prestera_fi_is_direct(struct fib_info *fi)
 {
-       struct fib_nh *fib_nh;
+       struct fib_nh_common *fib_nhc;
 
        if (fib_info_num_path(fi) == 1) {
-               fib_nh = fib_info_nh(fi, 0);
-               if (fib_nh->fib_nh_gw_family == AF_UNSPEC)
+               fib_nhc = fib_info_nhc(fi, 0);
+               if (fib_nhc->nhc_gw_family == AF_UNSPEC)
                        return true;
        }
 
@@ -261,7 +261,7 @@ static bool
 __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr,
                                       struct net_device *dev)
 {
-       struct fib_nh *fib_nh;
+       struct fib_nh_common *fib_nhc;
        struct fib_result res;
        bool reachable;
 
@@ -269,8 +269,8 @@ __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr,
 
        if (!prestera_util_kern_get_route(&res, tb_id, addr))
                if (prestera_fi_is_direct(res.fi)) {
-                       fib_nh = fib_info_nh(res.fi, 0);
-                       if (dev == fib_nh->fib_nh_dev)
+                       fib_nhc = fib_info_nhc(res.fi, 0);
+                       if (dev == fib_nhc->nhc_dev)
                                reachable = true;
                }
 
@@ -324,7 +324,7 @@ prestera_kern_fib_info_nhc(struct fib_notifier_info *info, int n)
        if (info->family == AF_INET) {
                fen4_info = container_of(info, struct fib_entry_notifier_info,
                                         info);
-               return &fib_info_nh(fen4_info->fi, n)->nh_common;
+               return fib_info_nhc(fen4_info->fi, n);
        } else if (info->family == AF_INET6) {
                fen6_info = container_of(info, struct fib6_entry_notifier_info,
                                         info);
index b0128336ff01a0028a3d6c8ad524d4f071714a00..e869c65d8e90f51eca0b5cb51dd7bf49d78bfd59 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. */
 
 #include "reporter_vnic.h"
+#include "en_stats.h"
 #include "devlink.h"
 
 #define VNIC_ENV_GET64(vnic_env_stats, c) \
@@ -36,55 +37,72 @@ int mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev,
        if (err)
                return err;
 
-       err = devlink_fmsg_u64_pair_put(fmsg, "total_error_queues",
-                                       VNIC_ENV_GET64(&vnic, total_error_queues));
-       if (err)
-               return err;
-
-       err = devlink_fmsg_u64_pair_put(fmsg, "send_queue_priority_update_flow",
-                                       VNIC_ENV_GET64(&vnic, send_queue_priority_update_flow));
-       if (err)
-               return err;
-
-       err = devlink_fmsg_u64_pair_put(fmsg, "comp_eq_overrun",
-                                       VNIC_ENV_GET64(&vnic, comp_eq_overrun));
-       if (err)
-               return err;
-
-       err = devlink_fmsg_u64_pair_put(fmsg, "async_eq_overrun",
-                                       VNIC_ENV_GET64(&vnic, async_eq_overrun));
-       if (err)
-               return err;
-
-       err = devlink_fmsg_u64_pair_put(fmsg, "cq_overrun",
-                                       VNIC_ENV_GET64(&vnic, cq_overrun));
-       if (err)
-               return err;
-
-       err = devlink_fmsg_u64_pair_put(fmsg, "invalid_command",
-                                       VNIC_ENV_GET64(&vnic, invalid_command));
-       if (err)
-               return err;
-
-       err = devlink_fmsg_u64_pair_put(fmsg, "quota_exceeded_command",
-                                       VNIC_ENV_GET64(&vnic, quota_exceeded_command));
-       if (err)
-               return err;
-
-       err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard",
-                                       VNIC_ENV_GET64(&vnic, nic_receive_steering_discard));
-       if (err)
-               return err;
-
-       err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail",
-                                       VNIC_ENV_GET64(&vnic, generated_pkt_steering_fail));
-       if (err)
-               return err;
-
-       err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail",
-                                       VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail));
-       if (err)
-               return err;
+       if (MLX5_CAP_GEN(dev, vnic_env_queue_counters)) {
+               err = devlink_fmsg_u32_pair_put(fmsg, "total_error_queues",
+                                               VNIC_ENV_GET(&vnic, total_error_queues));
+               if (err)
+                       return err;
+
+               err = devlink_fmsg_u32_pair_put(fmsg, "send_queue_priority_update_flow",
+                                               VNIC_ENV_GET(&vnic,
+                                                            send_queue_priority_update_flow));
+               if (err)
+                       return err;
+       }
+
+       if (MLX5_CAP_GEN(dev, eq_overrun_count)) {
+               err = devlink_fmsg_u32_pair_put(fmsg, "comp_eq_overrun",
+                                               VNIC_ENV_GET(&vnic, comp_eq_overrun));
+               if (err)
+                       return err;
+
+               err = devlink_fmsg_u32_pair_put(fmsg, "async_eq_overrun",
+                                               VNIC_ENV_GET(&vnic, async_eq_overrun));
+               if (err)
+                       return err;
+       }
+
+       if (MLX5_CAP_GEN(dev, vnic_env_cq_overrun)) {
+               err = devlink_fmsg_u32_pair_put(fmsg, "cq_overrun",
+                                               VNIC_ENV_GET(&vnic, cq_overrun));
+               if (err)
+                       return err;
+       }
+
+       if (MLX5_CAP_GEN(dev, invalid_command_count)) {
+               err = devlink_fmsg_u32_pair_put(fmsg, "invalid_command",
+                                               VNIC_ENV_GET(&vnic, invalid_command));
+               if (err)
+                       return err;
+       }
+
+       if (MLX5_CAP_GEN(dev, quota_exceeded_count)) {
+               err = devlink_fmsg_u32_pair_put(fmsg, "quota_exceeded_command",
+                                               VNIC_ENV_GET(&vnic, quota_exceeded_command));
+               if (err)
+                       return err;
+       }
+
+       if (MLX5_CAP_GEN(dev, nic_receive_steering_discard)) {
+               err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard",
+                                               VNIC_ENV_GET64(&vnic,
+                                                              nic_receive_steering_discard));
+               if (err)
+                       return err;
+       }
+
+       if (MLX5_CAP_GEN(dev, vnic_env_cnt_steering_fail)) {
+               err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail",
+                                               VNIC_ENV_GET64(&vnic,
+                                                              generated_pkt_steering_fail));
+               if (err)
+                       return err;
+
+               err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail",
+                                               VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail));
+               if (err)
+                       return err;
+       }
 
        err = devlink_fmsg_obj_nest_end(fmsg);
        if (err)
index f0c3464f037f4a0d0bc37047e7ace1b50ba8ff6c..1730f6a716eeabbaefcb954405c6f0e5cfd185e8 100644 (file)
@@ -1030,9 +1030,6 @@ int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv,
        int out_index;
        int err = 0;
 
-       if (!mlx5e_is_eswitch_flow(flow))
-               return 0;
-
        parse_attr = attr->parse_attr;
        esw_attr = attr->esw_attr;
        *vf_tun = false;
@@ -1464,10 +1461,12 @@ static void mlx5e_invalidate_encap(struct mlx5e_priv *priv,
                attr = mlx5e_tc_get_encap_attr(flow);
                esw_attr = attr->esw_attr;
 
-               if (flow_flag_test(flow, SLOW))
+               if (flow_flag_test(flow, SLOW)) {
                        mlx5e_tc_unoffload_from_slow_path(esw, flow);
-               else
+               } else {
                        mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr);
+                       mlx5e_tc_unoffload_flow_post_acts(flow);
+               }
 
                mlx5e_tc_detach_mod_hdr(priv, flow, attr);
                attr->modify_hdr = NULL;
index 9e8e6184f9e43cc7ef27e713cda754b47621a8d7..ecfe93a479da8e22b0da8a8f5116684e65d4b9ac 100644 (file)
@@ -84,6 +84,8 @@ enum mlx5e_xdp_xmit_mode {
  * MLX5E_XDP_XMIT_MODE_XSK:
  *    none.
  */
+#define MLX5E_XDP_FIFO_ENTRIES2DS_MAX_RATIO 4
+
 union mlx5e_xdp_info {
        enum mlx5e_xdp_xmit_mode mode;
        union {
index d97e6df66f454d4eac406658005052c63fee5fb8..b8dd744536553c55a22fca303cbff7ed03088551 100644 (file)
@@ -323,8 +323,11 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_linear(struct mlx5e_rq *rq,
        net_prefetch(mxbuf->xdp.data);
 
        prog = rcu_dereference(rq->xdp_prog);
-       if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf)))
+       if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf))) {
+               if (likely(__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)))
+                       wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
                return NULL; /* page/packet was consumed by XDP */
+       }
 
        /* XDP_PASS: copy the data from the UMEM to a new SKB. The frame reuse
         * will be handled by mlx5e_free_rx_wqe.
index dbe87bf89c0dd86843cb65a5639f42db0ea230ab..832d36be4a17b30bce77e9571d4fcfd39ac3b49b 100644 (file)
@@ -808,9 +808,9 @@ static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upsp
        }
 
        if (upspec->sport) {
-               MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_dport,
+               MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_sport,
                         upspec->sport_mask);
-               MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_dport, upspec->sport);
+               MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_sport, upspec->sport);
        }
 }
 
index eab5bc718771f0ae015ee067190fbd65b89435fb..8d995e304869232aa924c077e0a64cc168524a7c 100644 (file)
@@ -58,7 +58,9 @@ static int mlx5e_ipsec_remove_trailer(struct sk_buff *skb, struct xfrm_state *x)
 
        trailer_len = alen + plen + 2;
 
-       pskb_trim(skb, skb->len - trailer_len);
+       ret = pskb_trim(skb, skb->len - trailer_len);
+       if (unlikely(ret))
+               return ret;
        if (skb->protocol == htons(ETH_P_IP)) {
                ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len);
                ip_send_check(ipv4hdr);
index cf704f106b7c295ce236fa63916f1644f49f7ec6..984fa04bd331b8b22b8484f75538326c8ce5849f 100644 (file)
@@ -188,7 +188,6 @@ static void mlx5e_tls_debugfs_init(struct mlx5e_tls *tls,
 
 int mlx5e_ktls_init(struct mlx5e_priv *priv)
 {
-       struct mlx5_crypto_dek_pool *dek_pool;
        struct mlx5e_tls *tls;
 
        if (!mlx5e_is_ktls_device(priv->mdev))
@@ -199,12 +198,6 @@ int mlx5e_ktls_init(struct mlx5e_priv *priv)
                return -ENOMEM;
        tls->mdev = priv->mdev;
 
-       dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY);
-       if (IS_ERR(dek_pool)) {
-               kfree(tls);
-               return PTR_ERR(dek_pool);
-       }
-       tls->dek_pool = dek_pool;
        priv->tls = tls;
 
        mlx5e_tls_debugfs_init(tls, priv->dfs_root);
@@ -222,7 +215,6 @@ void mlx5e_ktls_cleanup(struct mlx5e_priv *priv)
        debugfs_remove_recursive(tls->debugfs.dfs);
        tls->debugfs.dfs = NULL;
 
-       mlx5_crypto_dek_pool_destroy(tls->dek_pool);
        kfree(priv->tls);
        priv->tls = NULL;
 }
index efb2cf74ad6a3ab2bc853b519175ed76f55fd1e2..d61be26a4df1a52508ea2b58dacc528fe0a37a4a 100644 (file)
@@ -908,28 +908,51 @@ static void mlx5e_tls_tx_debugfs_init(struct mlx5e_tls *tls,
 
 int mlx5e_ktls_init_tx(struct mlx5e_priv *priv)
 {
+       struct mlx5_crypto_dek_pool *dek_pool;
        struct mlx5e_tls *tls = priv->tls;
+       int err;
+
+       if (!mlx5e_is_ktls_device(priv->mdev))
+               return 0;
+
+       /* DEK pool could be used by either or both of TX and RX. But we have to
+        * put the creation here to avoid syndrome when doing devlink reload.
+        */
+       dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY);
+       if (IS_ERR(dek_pool))
+               return PTR_ERR(dek_pool);
+       tls->dek_pool = dek_pool;
 
        if (!mlx5e_is_ktls_tx(priv->mdev))
                return 0;
 
        priv->tls->tx_pool = mlx5e_tls_tx_pool_init(priv->mdev, &priv->tls->sw_stats);
-       if (!priv->tls->tx_pool)
-               return -ENOMEM;
+       if (!priv->tls->tx_pool) {
+               err = -ENOMEM;
+               goto err_tx_pool_init;
+       }
 
        mlx5e_tls_tx_debugfs_init(tls, tls->debugfs.dfs);
 
        return 0;
+
+err_tx_pool_init:
+       mlx5_crypto_dek_pool_destroy(dek_pool);
+       return err;
 }
 
 void mlx5e_ktls_cleanup_tx(struct mlx5e_priv *priv)
 {
        if (!mlx5e_is_ktls_tx(priv->mdev))
-               return;
+               goto dek_pool_destroy;
 
        debugfs_remove_recursive(priv->tls->debugfs.dfs_tx);
        priv->tls->debugfs.dfs_tx = NULL;
 
        mlx5e_tls_tx_pool_cleanup(priv->tls->tx_pool);
        priv->tls->tx_pool = NULL;
+
+dek_pool_destroy:
+       if (mlx5e_is_ktls_device(priv->mdev))
+               mlx5_crypto_dek_pool_destroy(priv->tls->dek_pool);
 }
index 7fc901a6ec5fcbb5bb5433aedf156eb318f7d052..414e28584881349932437aaf000e62ad5684eef8 100644 (file)
@@ -161,6 +161,7 @@ static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft)
 
        if (!in) {
                kfree(ft->g);
+               ft->g = NULL;
                return -ENOMEM;
        }
 
index 933a7772a7a396728f6eb27790896f69ede981f7..5aa51d74f8b43ad01366dd299bee59a5d63cc059 100644 (file)
@@ -135,6 +135,16 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs);
 
 int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs)
 {
+       /* Moving to switchdev mode, fs->arfs is freed by mlx5e_nic_profile
+        * cleanup_rx callback and it is not recreated when
+        * mlx5e_uplink_rep_profile is loaded as mlx5e_create_flow_steering()
+        * is not called by the uplink_rep profile init_rx callback. Thus, if
+        * ntuple is set, moving to switchdev flow will enter this function
+        * with fs->arfs nullified.
+        */
+       if (!mlx5e_fs_get_arfs(fs))
+               return 0;
+
        arfs_del_rules(fs);
 
        return arfs_disable(fs);
index defb1efccb78fa5ee067eb7ed2ce8cdd2a603040..f7b494125eee8383f45ff6f165e1d63ca330c298 100644 (file)
@@ -1036,7 +1036,23 @@ static int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, int next_s
        return err;
 }
 
-static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
+static void mlx5e_flush_rq_cq(struct mlx5e_rq *rq)
+{
+       struct mlx5_cqwq *cqwq = &rq->cq.wq;
+       struct mlx5_cqe64 *cqe;
+
+       if (test_bit(MLX5E_RQ_STATE_MINI_CQE_ENHANCED, &rq->state)) {
+               while ((cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq)))
+                       mlx5_cqwq_pop(cqwq);
+       } else {
+               while ((cqe = mlx5_cqwq_get_cqe(cqwq)))
+                       mlx5_cqwq_pop(cqwq);
+       }
+
+       mlx5_cqwq_update_db_record(cqwq);
+}
+
+int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state)
 {
        struct net_device *dev = rq->netdev;
        int err;
@@ -1046,6 +1062,10 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
                netdev_err(dev, "Failed to move rq 0x%x to reset\n", rq->rqn);
                return err;
        }
+
+       mlx5e_free_rx_descs(rq);
+       mlx5e_flush_rq_cq(rq);
+
        err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
        if (err) {
                netdev_err(dev, "Failed to move rq 0x%x to ready\n", rq->rqn);
@@ -1055,13 +1075,6 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
        return 0;
 }
 
-int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state)
-{
-       mlx5e_free_rx_descs(rq);
-
-       return mlx5e_rq_to_ready(rq, curr_state);
-}
-
 static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd)
 {
        struct mlx5_core_dev *mdev = rq->mdev;
@@ -1285,11 +1298,13 @@ static int mlx5e_alloc_xdpsq_fifo(struct mlx5e_xdpsq *sq, int numa)
 {
        struct mlx5e_xdp_info_fifo *xdpi_fifo = &sq->db.xdpi_fifo;
        int wq_sz        = mlx5_wq_cyc_get_size(&sq->wq);
-       int entries = wq_sz * MLX5_SEND_WQEBB_NUM_DS * 2; /* upper bound for maximum num of
-                                                          * entries of all xmit_modes.
-                                                          */
+       int entries;
        size_t size;
 
+       /* upper bound for maximum num of entries of all xmit_modes. */
+       entries = roundup_pow_of_two(wq_sz * MLX5_SEND_WQEBB_NUM_DS *
+                                    MLX5E_XDP_FIFO_ENTRIES2DS_MAX_RATIO);
+
        size = array_size(sizeof(*xdpi_fifo->xi), entries);
        xdpi_fifo->xi = kvzalloc_node(size, GFP_KERNEL, numa);
        if (!xdpi_fifo->xi)
@@ -5253,6 +5268,7 @@ void mlx5e_destroy_q_counters(struct mlx5e_priv *priv)
 static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
                          struct net_device *netdev)
 {
+       const bool take_rtnl = netdev->reg_state == NETREG_REGISTERED;
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5e_flow_steering *fs;
        int err;
@@ -5281,9 +5297,19 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
                mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
 
        mlx5e_health_create_reporters(priv);
+
+       /* If netdev is already registered (e.g. move from uplink to nic profile),
+        * RTNL lock must be held before triggering netdev notifiers.
+        */
+       if (take_rtnl)
+               rtnl_lock();
+
        /* update XDP supported features */
        mlx5e_set_xdp_feature(netdev);
 
+       if (take_rtnl)
+               rtnl_unlock();
+
        return 0;
 }
 
index 152b62138450f9855578489a43e047a351978349..99b3843396f3372c04614d7fefeb71d231d18b56 100644 (file)
@@ -1012,7 +1012,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
        err = mlx5e_open_drop_rq(priv, &priv->drop_rq);
        if (err) {
                mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
-               return err;
+               goto err_rx_res_free;
        }
 
        err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0,
@@ -1046,6 +1046,7 @@ err_destroy_rx_res:
        mlx5e_rx_res_destroy(priv->rx_res);
 err_close_drop_rq:
        mlx5e_close_drop_rq(&priv->drop_rq);
+err_rx_res_free:
        mlx5e_rx_res_free(priv->rx_res);
        priv->rx_res = NULL;
 err_free_fs:
@@ -1159,6 +1160,10 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
                return err;
        }
 
+       err = mlx5e_rep_neigh_init(rpriv);
+       if (err)
+               goto err_neigh_init;
+
        if (rpriv->rep->vport == MLX5_VPORT_UPLINK) {
                err = mlx5e_init_uplink_rep_tx(rpriv);
                if (err)
@@ -1175,6 +1180,8 @@ err_ht_init:
        if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
                mlx5e_cleanup_uplink_rep_tx(rpriv);
 err_init_tx:
+       mlx5e_rep_neigh_cleanup(rpriv);
+err_neigh_init:
        mlx5e_destroy_tises(priv);
        return err;
 }
@@ -1188,22 +1195,17 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv)
        if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
                mlx5e_cleanup_uplink_rep_tx(rpriv);
 
+       mlx5e_rep_neigh_cleanup(rpriv);
        mlx5e_destroy_tises(priv);
 }
 
 static void mlx5e_rep_enable(struct mlx5e_priv *priv)
 {
-       struct mlx5e_rep_priv *rpriv = priv->ppriv;
-
        mlx5e_set_netdev_mtu_boundaries(priv);
-       mlx5e_rep_neigh_init(rpriv);
 }
 
 static void mlx5e_rep_disable(struct mlx5e_priv *priv)
 {
-       struct mlx5e_rep_priv *rpriv = priv->ppriv;
-
-       mlx5e_rep_neigh_cleanup(rpriv);
 }
 
 static int mlx5e_update_rep_rx(struct mlx5e_priv *priv)
@@ -1253,7 +1255,6 @@ static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event
 
 static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
 {
-       struct mlx5e_rep_priv *rpriv = priv->ppriv;
        struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
        u16 max_mtu;
@@ -1275,7 +1276,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
        mlx5_notifier_register(mdev, &priv->events_nb);
        mlx5e_dcbnl_initialize(priv);
        mlx5e_dcbnl_init_app(priv);
-       mlx5e_rep_neigh_init(rpriv);
        mlx5e_rep_bridge_init(priv);
 
        netdev->wanted_features |= NETIF_F_HW_TC;
@@ -1290,7 +1290,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
 
 static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
 {
-       struct mlx5e_rep_priv *rpriv = priv->ppriv;
        struct mlx5_core_dev *mdev = priv->mdev;
 
        rtnl_lock();
@@ -1300,7 +1299,6 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
        rtnl_unlock();
 
        mlx5e_rep_bridge_cleanup(priv);
-       mlx5e_rep_neigh_cleanup(rpriv);
        mlx5e_dcbnl_delete_app(priv);
        mlx5_notifier_unregister(mdev, &priv->events_nb);
        mlx5e_rep_tc_disable(priv);
index 8d0a3f69693e113a2e215166e76020b35b2372f6..31708d5aa608725cc3060b887fd951c7242a7489 100644 (file)
@@ -1725,6 +1725,19 @@ verify_attr_actions(u32 actions, struct netlink_ext_ack *extack)
        return 0;
 }
 
+static bool
+has_encap_dests(struct mlx5_flow_attr *attr)
+{
+       struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
+       int out_index;
+
+       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++)
+               if (esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)
+                       return true;
+
+       return false;
+}
+
 static int
 post_process_attr(struct mlx5e_tc_flow *flow,
                  struct mlx5_flow_attr *attr,
@@ -1737,9 +1750,11 @@ post_process_attr(struct mlx5e_tc_flow *flow,
        if (err)
                goto err_out;
 
-       err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
-       if (err)
-               goto err_out;
+       if (mlx5e_is_eswitch_flow(flow) && has_encap_dests(attr)) {
+               err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
+               if (err)
+                       goto err_out;
+       }
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
                err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr);
@@ -1928,9 +1943,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5_flow_attr *attr = flow->attr;
-       struct mlx5_esw_flow_attr *esw_attr;
 
-       esw_attr = attr->esw_attr;
        mlx5e_put_flow_tunnel_id(flow);
 
        remove_unready_flow(flow);
@@ -1951,12 +1964,6 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
 
        mlx5_tc_ct_match_del(get_ct_priv(priv), &flow->attr->ct_attr);
 
-       if (esw_attr->int_port)
-               mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->int_port);
-
-       if (esw_attr->dest_int_port)
-               mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->dest_int_port);
-
        if (flow_flag_test(flow, L3_TO_L2_DECAP))
                mlx5e_detach_decap(priv, flow);
 
@@ -4253,6 +4260,7 @@ static void
 mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr)
 {
        struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow);
+       struct mlx5_esw_flow_attr *esw_attr;
 
        if (!attr)
                return;
@@ -4270,6 +4278,18 @@ mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *a
                mlx5e_tc_detach_mod_hdr(flow->priv, flow, attr);
        }
 
+       if (mlx5e_is_eswitch_flow(flow)) {
+               esw_attr = attr->esw_attr;
+
+               if (esw_attr->int_port)
+                       mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv),
+                                             esw_attr->int_port);
+
+               if (esw_attr->dest_int_port)
+                       mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv),
+                                             esw_attr->dest_int_port);
+       }
+
        mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr);
 
        free_branch_attr(flow, attr->branch_true);
index b6a45eff28f554be7456be783ad24f4b104ae0b5..dbd7cbe6cbf3632d5ce97a0ee0d39a53d4d37a88 100644 (file)
@@ -64,7 +64,7 @@ void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_
 
        bridge->debugfs_dir = debugfs_create_dir(br_netdev->name,
                                                 bridge->br_offloads->debugfs_root);
-       debugfs_create_file("fdb", 0444, bridge->debugfs_dir, bridge,
+       debugfs_create_file("fdb", 0400, bridge->debugfs_dir, bridge,
                            &mlx5_esw_bridge_debugfs_fops);
 }
 
index af779c700278ed4f4c5c4c203c231de85ffbe731..fdf2be548e855d29842ef8ba66b1e71ca5a4cf9b 100644 (file)
@@ -60,7 +60,7 @@ static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16
        }  else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) {
                memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
                dl_port->attrs.switch_id.id_len = ppid.id_len;
-               devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum,
+               devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum,
                                              vport_num - 1, false);
        }
        return dl_port;
index bdfe609cc9ec4a4924901ef4c687ad9384a21e02..e59380ee1ead32761fce8c62b5cf9c3884c3e56a 100644 (file)
@@ -1436,7 +1436,6 @@ esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
 
        esw_init_chains_offload_flags(esw, &attr.flags);
        attr.ns = MLX5_FLOW_NAMESPACE_FDB;
-       attr.fs_base_prio = FDB_TC_OFFLOAD;
        attr.max_grp_num = esw->params.large_group_num;
        attr.default_ft = miss_fdb;
        attr.mapping = esw->offloads.reg_c0_obj_pool;
@@ -2779,9 +2778,9 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
                                         struct mlx5_eswitch *peer_esw,
                                         bool pair)
 {
-       u8 peer_idx = mlx5_get_dev_index(peer_esw->dev);
+       u16 peer_vhca_id = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
+       u16 vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id);
        struct mlx5_flow_root_namespace *peer_ns;
-       u8 idx = mlx5_get_dev_index(esw->dev);
        struct mlx5_flow_root_namespace *ns;
        int err;
 
@@ -2789,18 +2788,18 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
        ns = esw->dev->priv.steering->fdb_root_ns;
 
        if (pair) {
-               err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_idx);
+               err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_vhca_id);
                if (err)
                        return err;
 
-               err = mlx5_flow_namespace_set_peer(peer_ns, ns, idx);
+               err = mlx5_flow_namespace_set_peer(peer_ns, ns, vhca_id);
                if (err) {
-                       mlx5_flow_namespace_set_peer(ns, NULL, peer_idx);
+                       mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id);
                        return err;
                }
        } else {
-               mlx5_flow_namespace_set_peer(ns, NULL, peer_idx);
-               mlx5_flow_namespace_set_peer(peer_ns, NULL, idx);
+               mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id);
+               mlx5_flow_namespace_set_peer(peer_ns, NULL, vhca_id);
        }
 
        return 0;
@@ -4196,7 +4195,7 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable,
        }
 
        hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
-       MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, 1);
+       MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, enable);
 
        err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport,
                                            MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE2);
index 91dcb0dcad101ef640b8113e51409988d9d11a00..244cfd470903522cf93f02a73c0a643627dd90c7 100644 (file)
@@ -140,7 +140,7 @@ static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace
 
 static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns,
                                  struct mlx5_flow_root_namespace *peer_ns,
-                                 u8 peer_idx)
+                                 u16 peer_vhca_id)
 {
        return 0;
 }
@@ -245,12 +245,20 @@ static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns,
            mlx5_lag_is_shared_fdb(dev) &&
            mlx5_lag_is_master(dev)) {
                struct mlx5_core_dev *peer_dev;
-               int i;
+               int i, j;
 
                mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) {
                        err = mlx5_cmd_set_slave_root_fdb(dev, peer_dev, !disconnect,
                                                          (!disconnect) ? ft->id : 0);
                        if (err && !disconnect) {
+                               mlx5_lag_for_each_peer_mdev(dev, peer_dev, j) {
+                                       if (j < i)
+                                               mlx5_cmd_set_slave_root_fdb(dev, peer_dev, 1,
+                                                                           ns->root_ft->id);
+                                       else
+                                               break;
+                               }
+
                                MLX5_SET(set_flow_table_root_in, in, op_mod, 0);
                                MLX5_SET(set_flow_table_root_in, in, table_id,
                                         ns->root_ft->id);
index b6b9a5a20591dfe59e8213fd3f92987d1c8d4ebd..7790ae5531e1d3461c0103c93341745d4227c375 100644 (file)
@@ -94,7 +94,7 @@ struct mlx5_flow_cmds {
 
        int (*set_peer)(struct mlx5_flow_root_namespace *ns,
                        struct mlx5_flow_root_namespace *peer_ns,
-                       u8 peer_idx);
+                       u16 peer_vhca_id);
 
        int (*create_ns)(struct mlx5_flow_root_namespace *ns);
        int (*destroy_ns)(struct mlx5_flow_root_namespace *ns);
index 4ef04aa287719ee469ca8f0e47453b7929719fd1..6b069fa411c5a1cd1d2bfcf1f3fd893deb2edfd3 100644 (file)
@@ -889,7 +889,7 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node  *root,
        struct fs_node *iter = list_entry(start, struct fs_node, list);
        struct mlx5_flow_table *ft = NULL;
 
-       if (!root || root->type == FS_TYPE_PRIO_CHAINS)
+       if (!root)
                return NULL;
 
        list_for_each_advance_continue(iter, &root->children, reverse) {
@@ -905,20 +905,42 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node  *root,
        return ft;
 }
 
-/* If reverse is false then return the first flow table in next priority of
- * prio in the tree, else return the last flow table in the previous priority
- * of prio in the tree.
+static struct fs_node *find_prio_chains_parent(struct fs_node *parent,
+                                              struct fs_node **child)
+{
+       struct fs_node *node = NULL;
+
+       while (parent && parent->type != FS_TYPE_PRIO_CHAINS) {
+               node = parent;
+               parent = parent->parent;
+       }
+
+       if (child)
+               *child = node;
+
+       return parent;
+}
+
+/* If reverse is false then return the first flow table next to the passed node
+ * in the tree, else return the last flow table before the node in the tree.
+ * If skip is true, skip the flow tables in the same prio_chains prio.
  */
-static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse)
+static struct mlx5_flow_table *find_closest_ft(struct fs_node *node, bool reverse,
+                                              bool skip)
 {
+       struct fs_node *prio_chains_parent = NULL;
        struct mlx5_flow_table *ft = NULL;
        struct fs_node *curr_node;
        struct fs_node *parent;
 
-       parent = prio->node.parent;
-       curr_node = &prio->node;
+       if (skip)
+               prio_chains_parent = find_prio_chains_parent(node, NULL);
+       parent = node->parent;
+       curr_node = node;
        while (!ft && parent) {
-               ft = find_closest_ft_recursive(parent, &curr_node->list, reverse);
+               if (parent != prio_chains_parent)
+                       ft = find_closest_ft_recursive(parent, &curr_node->list,
+                                                      reverse);
                curr_node = parent;
                parent = curr_node->parent;
        }
@@ -926,15 +948,15 @@ static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool revers
 }
 
 /* Assuming all the tree is locked by mutex chain lock */
-static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio)
+static struct mlx5_flow_table *find_next_chained_ft(struct fs_node *node)
 {
-       return find_closest_ft(prio, false);
+       return find_closest_ft(node, false, true);
 }
 
 /* Assuming all the tree is locked by mutex chain lock */
-static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
+static struct mlx5_flow_table *find_prev_chained_ft(struct fs_node *node)
 {
-       return find_closest_ft(prio, true);
+       return find_closest_ft(node, true, true);
 }
 
 static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
@@ -946,7 +968,7 @@ static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
        next_ns = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS;
        fs_get_obj(prio, next_ns ? ft->ns->node.parent : ft->node.parent);
 
-       return find_next_chained_ft(prio);
+       return find_next_chained_ft(&prio->node);
 }
 
 static int connect_fts_in_prio(struct mlx5_core_dev *dev,
@@ -970,21 +992,55 @@ static int connect_fts_in_prio(struct mlx5_core_dev *dev,
        return 0;
 }
 
+static struct mlx5_flow_table *find_closet_ft_prio_chains(struct fs_node *node,
+                                                         struct fs_node *parent,
+                                                         struct fs_node **child,
+                                                         bool reverse)
+{
+       struct mlx5_flow_table *ft;
+
+       ft = find_closest_ft(node, reverse, false);
+
+       if (ft && parent == find_prio_chains_parent(&ft->node, child))
+               return ft;
+
+       return NULL;
+}
+
 /* Connect flow tables from previous priority of prio to ft */
 static int connect_prev_fts(struct mlx5_core_dev *dev,
                            struct mlx5_flow_table *ft,
                            struct fs_prio *prio)
 {
+       struct fs_node *prio_parent, *parent = NULL, *child, *node;
        struct mlx5_flow_table *prev_ft;
+       int err = 0;
+
+       prio_parent = find_prio_chains_parent(&prio->node, &child);
+
+       /* return directly if not under the first sub ns of prio_chains prio */
+       if (prio_parent && !list_is_first(&child->list, &prio_parent->children))
+               return 0;
 
-       prev_ft = find_prev_chained_ft(prio);
-       if (prev_ft) {
+       prev_ft = find_prev_chained_ft(&prio->node);
+       while (prev_ft) {
                struct fs_prio *prev_prio;
 
                fs_get_obj(prev_prio, prev_ft->node.parent);
-               return connect_fts_in_prio(dev, prev_prio, ft);
+               err = connect_fts_in_prio(dev, prev_prio, ft);
+               if (err)
+                       break;
+
+               if (!parent) {
+                       parent = find_prio_chains_parent(&prev_prio->node, &child);
+                       if (!parent)
+                               break;
+               }
+
+               node = child;
+               prev_ft = find_closet_ft_prio_chains(node, parent, &child, true);
        }
-       return 0;
+       return err;
 }
 
 static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
@@ -1123,7 +1179,7 @@ static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table
                if (err)
                        return err;
 
-               next_ft = first_ft ? first_ft : find_next_chained_ft(prio);
+               next_ft = first_ft ? first_ft : find_next_chained_ft(&prio->node);
                err = connect_fwd_rules(dev, ft, next_ft);
                if (err)
                        return err;
@@ -1198,7 +1254,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
 
        tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table);
        next_ft = unmanaged ? ft_attr->next_ft :
-                             find_next_chained_ft(fs_prio);
+                             find_next_chained_ft(&fs_prio->node);
        ft->def_miss_action = ns->def_miss_action;
        ft->ns = ns;
        err = root->cmds->create_flow_table(root, ft, ft_attr, next_ft);
@@ -2195,13 +2251,20 @@ EXPORT_SYMBOL(mlx5_del_flow_rules);
 /* Assuming prio->node.children(flow tables) is sorted by level */
 static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
 {
+       struct fs_node *prio_parent, *child;
        struct fs_prio *prio;
 
        fs_get_obj(prio, ft->node.parent);
 
        if (!list_is_last(&ft->node.list, &prio->node.children))
                return list_next_entry(ft, node.list);
-       return find_next_chained_ft(prio);
+
+       prio_parent = find_prio_chains_parent(&prio->node, &child);
+
+       if (prio_parent && list_is_first(&child->list, &prio_parent->children))
+               return find_closest_ft(&prio->node, false, false);
+
+       return find_next_chained_ft(&prio->node);
 }
 
 static int update_root_ft_destroy(struct mlx5_flow_table *ft)
@@ -3621,7 +3684,7 @@ void mlx5_destroy_match_definer(struct mlx5_core_dev *dev,
 
 int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
                                 struct mlx5_flow_root_namespace *peer_ns,
-                                u8 peer_idx)
+                                u16 peer_vhca_id)
 {
        if (peer_ns && ns->mode != peer_ns->mode) {
                mlx5_core_err(ns->dev,
@@ -3629,7 +3692,7 @@ int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
                return -EINVAL;
        }
 
-       return ns->cmds->set_peer(ns, peer_ns, peer_idx);
+       return ns->cmds->set_peer(ns, peer_ns, peer_vhca_id);
 }
 
 /* This function should be called only at init stage of the namespace.
index 03e64c4c245da3e170eb636fa7049fe792525e76..4aed1768b85fbf9dbe68ab006b7ad2d706afe51d 100644 (file)
@@ -303,7 +303,7 @@ const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void);
 
 int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
                                 struct mlx5_flow_root_namespace *peer_ns,
-                                u8 peer_idx);
+                                u16 peer_vhca_id);
 
 int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns,
                                 enum mlx5_flow_steering_mode mode);
index d3a3fe4ce670260f30436a7274cc9ebbeb4ac87c..7d9bbb494d95b329557839e62f0ac3846f519440 100644 (file)
@@ -574,7 +574,7 @@ static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
        for (i = 0; i < ldev->ports; i++) {
                for (j = 0; j < ldev->buckets; j++) {
                        idx = i * ldev->buckets + j;
-                       if (ldev->v2p_map[i] == ports[i])
+                       if (ldev->v2p_map[idx] == ports[idx])
                                continue;
 
                        dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev,
index 973babfaff25cd84dc562cfb5491e86a9986c861..377372f0578ae47a2ab07de24243795730b9f1bd 100644 (file)
@@ -227,10 +227,15 @@ static void mlx5_timestamp_overflow(struct work_struct *work)
        clock = container_of(timer, struct mlx5_clock, timer);
        mdev = container_of(clock, struct mlx5_core_dev, clock);
 
+       if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+               goto out;
+
        write_seqlock_irqsave(&clock->lock, flags);
        timecounter_read(&timer->tc);
        mlx5_update_clock_info_page(mdev);
        write_sequnlock_irqrestore(&clock->lock, flags);
+
+out:
        schedule_delayed_work(&timer->overflow_work, timer->overflow_period);
 }
 
index db9df9798ffac0a7e6f63ebfc9c5e2fe21ae36fe..a80ecb672f33dd2319b230bdc3d5eece550bcdcb 100644 (file)
@@ -178,7 +178,7 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains,
        if (!mlx5_chains_ignore_flow_level_supported(chains) ||
            (chain == 0 && prio == 1 && level == 0)) {
                ft_attr.level = chains->fs_base_level;
-               ft_attr.prio = chains->fs_base_prio;
+               ft_attr.prio = chains->fs_base_prio + prio - 1;
                ns = (chains->ns == MLX5_FLOW_NAMESPACE_FDB) ?
                        mlx5_get_fdb_sub_ns(chains->dev, chain) :
                        mlx5_get_flow_namespace(chains->dev, chains->ns);
index 88dbea6631d507befd6d59a253928bce901912d0..72ae560a1c68459f91a309e8b2a1d4dbc65a2a5c 100644 (file)
@@ -1506,6 +1506,7 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev)
        if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
                mlx5_core_warn(dev, "%s: interface is down, NOP\n",
                               __func__);
+               mlx5_devlink_params_unregister(priv_to_devlink(dev));
                mlx5_cleanup_once(dev);
                goto out;
        }
@@ -1988,7 +1989,7 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
 
        mlx5_enter_error_state(dev, false);
        mlx5_error_sw_reset(dev);
-       mlx5_unload_one(dev, true);
+       mlx5_unload_one(dev, false);
        mlx5_drain_health_wq(dev);
        mlx5_pci_disable_device(dev);
 
index c4be257c043d4fe1702951b6178392b49b6e1ad4..682d3dc00dd19ada56bcc93a91fa1381de68d89d 100644 (file)
@@ -361,7 +361,7 @@ static inline bool mlx5_core_is_ec_vf_vport(const struct mlx5_core_dev *dev, u16
 
 static inline int mlx5_vport_to_func_id(const struct mlx5_core_dev *dev, u16 vport, bool ec_vf_func)
 {
-       return ec_vf_func ? vport - mlx5_core_ec_vf_vport_base(dev)
+       return ec_vf_func ? vport - mlx5_core_ec_vf_vport_base(dev) + 1
                          : vport;
 }
 
index 4e42a3b9b8eecb4f9f0786c19d69c8e459754661..a2fc937d54617c28781e1171e7ca94f3c6d0efe3 100644 (file)
@@ -285,8 +285,7 @@ static u16 mlx5_get_max_vfs(struct mlx5_core_dev *dev)
                host_total_vfs = MLX5_GET(query_esw_functions_out, out,
                                          host_params_context.host_total_vfs);
                kvfree(out);
-               if (host_total_vfs)
-                       return host_total_vfs;
+               return host_total_vfs;
        }
 
 done:
index e739ec6cdf901a7686f451d266e3d1470eabd27e..54bb0866ed72758c801ec6406bd23cbcaa150d86 100644 (file)
@@ -2079,7 +2079,7 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn,
 
        peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) &&
                (vhca_id != dmn->info.caps.gvmi);
-       vport_dmn = peer_vport ? dmn->peer_dmn[vhca_id] : dmn;
+       vport_dmn = peer_vport ? xa_load(&dmn->peer_dmn_xa, vhca_id) : dmn;
        if (!vport_dmn) {
                mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n");
                return NULL;
index 7491911ebcb50d00f608e046755b3834aa4848b0..8c2a34a0d6be84efc30eac6b4fdbc04202addcc4 100644 (file)
@@ -564,11 +564,12 @@ int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
 
        err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
        if (err)
-               return err;
+               goto err_free_in;
 
        *reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
-       kvfree(in);
 
+err_free_in:
+       kvfree(in);
        return err;
 }
 
index 75dc85dc24ef212a34aa02e4173fc25b17b53154..3d74109f82300ee2256a92d047ce3e429b6343a0 100644 (file)
@@ -475,6 +475,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
        mutex_init(&dmn->info.rx.mutex);
        mutex_init(&dmn->info.tx.mutex);
        xa_init(&dmn->definers_xa);
+       xa_init(&dmn->peer_dmn_xa);
 
        if (dr_domain_caps_init(mdev, dmn)) {
                mlx5dr_err(dmn, "Failed init domain, no caps\n");
@@ -507,6 +508,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
 uninit_caps:
        dr_domain_caps_uninit(dmn);
 def_xa_destroy:
+       xa_destroy(&dmn->peer_dmn_xa);
        xa_destroy(&dmn->definers_xa);
        kfree(dmn);
        return NULL;
@@ -547,6 +549,7 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn)
        dr_domain_uninit_csum_recalc_fts(dmn);
        dr_domain_uninit_resources(dmn);
        dr_domain_caps_uninit(dmn);
+       xa_destroy(&dmn->peer_dmn_xa);
        xa_destroy(&dmn->definers_xa);
        mutex_destroy(&dmn->info.tx.mutex);
        mutex_destroy(&dmn->info.rx.mutex);
@@ -556,17 +559,21 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn)
 
 void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn,
                            struct mlx5dr_domain *peer_dmn,
-                           u8 peer_idx)
+                           u16 peer_vhca_id)
 {
+       struct mlx5dr_domain *peer;
+
        mlx5dr_domain_lock(dmn);
 
-       if (dmn->peer_dmn[peer_idx])
-               refcount_dec(&dmn->peer_dmn[peer_idx]->refcount);
+       peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id);
+       if (peer)
+               refcount_dec(&peer->refcount);
 
-       dmn->peer_dmn[peer_idx] = peer_dmn;
+       WARN_ON(xa_err(xa_store(&dmn->peer_dmn_xa, peer_vhca_id, peer_dmn, GFP_KERNEL)));
 
-       if (dmn->peer_dmn[peer_idx])
-               refcount_inc(&dmn->peer_dmn[peer_idx]->refcount);
+       peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id);
+       if (peer)
+               refcount_inc(&peer->refcount);
 
        mlx5dr_domain_unlock(dmn);
 }
index d6947fe13d560d141e8e2efa9c7be49a485abcc0..8ca534ef5d031682372ddba1c6a5431be43c0535 100644 (file)
@@ -82,7 +82,7 @@ dr_ptrn_alloc_pattern(struct mlx5dr_ptrn_mgr *mgr,
        u32 chunk_size;
        u32 index;
 
-       chunk_size = ilog2(num_of_actions);
+       chunk_size = ilog2(roundup_pow_of_two(num_of_actions));
        /* HW modify action index granularity is at least 64B */
        chunk_size = max_t(u32, chunk_size, DR_CHUNK_SIZE_8);
 
index 69d7a8f3c402e31a942eea82bce6e4deb231d5a0..f708b029425ac00289a805f636e88c1d837c2bc7 100644 (file)
@@ -1652,17 +1652,18 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
        struct mlx5dr_domain *dmn = sb->dmn;
        struct mlx5dr_domain *vport_dmn;
        u8 *bit_mask = sb->bit_mask;
+       struct mlx5dr_domain *peer;
        bool source_gvmi_set;
 
        DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
 
        if (sb->vhca_id_valid) {
+               peer = xa_load(&dmn->peer_dmn_xa, id);
                /* Find port GVMI based on the eswitch_owner_vhca_id */
                if (id == dmn->info.caps.gvmi)
                        vport_dmn = dmn;
-               else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] &&
-                        (id == dmn->peer_dmn[id]->info.caps.gvmi))
-                       vport_dmn = dmn->peer_dmn[id];
+               else if (peer && (id == peer->info.caps.gvmi))
+                       vport_dmn = peer;
                else
                        return -EINVAL;
 
index f4ef0b22b991211c83c8a914fab296ace8355996..dd856cde188de9ed366a70286a9abdd600d00935 100644 (file)
@@ -1984,16 +1984,17 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
        struct mlx5dr_domain *dmn = sb->dmn;
        struct mlx5dr_domain *vport_dmn;
        u8 *bit_mask = sb->bit_mask;
+       struct mlx5dr_domain *peer;
 
        DR_STE_SET_TAG(src_gvmi_qp_v1, tag, source_qp, misc, source_sqn);
 
        if (sb->vhca_id_valid) {
+               peer = xa_load(&dmn->peer_dmn_xa, id);
                /* Find port GVMI based on the eswitch_owner_vhca_id */
                if (id == dmn->info.caps.gvmi)
                        vport_dmn = dmn;
-               else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] &&
-                        (id == dmn->peer_dmn[id]->info.caps.gvmi))
-                       vport_dmn = dmn->peer_dmn[id];
+               else if (peer && (id == peer->info.caps.gvmi))
+                       vport_dmn = peer;
                else
                        return -EINVAL;
 
index 1622dbbe6b970d2cb66e53de2857485f6bc78a41..6c59de3e28f6568fb16ec76287ca99b8b1da3733 100644 (file)
@@ -935,7 +935,6 @@ struct mlx5dr_domain_info {
 };
 
 struct mlx5dr_domain {
-       struct mlx5dr_domain *peer_dmn[MLX5_MAX_PORTS];
        struct mlx5_core_dev *mdev;
        u32 pdn;
        struct mlx5_uars_page *uar;
@@ -956,6 +955,7 @@ struct mlx5dr_domain {
        struct list_head dbg_tbl_list;
        struct mlx5dr_dbg_dump_info dump_info;
        struct xarray definers_xa;
+       struct xarray peer_dmn_xa;
        /* memory management statistics */
        u32 num_buddies[DR_ICM_TYPE_MAX];
 };
index 6aac5f006bf8b1ae63a78ef681bc08a2a326c761..feb307fb3440bd1264cf6f27a50f00aaf29986ad 100644 (file)
@@ -781,14 +781,14 @@ restore_fte:
 
 static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns,
                                struct mlx5_flow_root_namespace *peer_ns,
-                               u8 peer_idx)
+                               u16 peer_vhca_id)
 {
        struct mlx5dr_domain *peer_domain = NULL;
 
        if (peer_ns)
                peer_domain = peer_ns->fs_dr_domain.dr_domain;
        mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain,
-                              peer_domain, peer_idx);
+                              peer_domain, peer_vhca_id);
        return 0;
 }
 
index 24cbb33ecd6c99c117992952ce95899dde208d87..89fced86936f64ce24281c1d8c68956807e7eb00 100644 (file)
@@ -49,7 +49,7 @@ int mlx5dr_domain_sync(struct mlx5dr_domain *domain, u32 flags);
 
 void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn,
                            struct mlx5dr_domain *peer_dmn,
-                           u8 peer_idx);
+                           u16 peer_vhca_id);
 
 struct mlx5dr_table *
 mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags,
index a499e460594b6598bdd501cf5d27084af5c15b73..c2ad0921e893c68f9447cdb6b491bc1c23346e55 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/ethtool.h>
 #include <linux/filter.h>
 #include <linux/mm.h>
+#include <linux/pci.h>
 
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
@@ -2345,9 +2346,12 @@ int mana_attach(struct net_device *ndev)
 static int mana_dealloc_queues(struct net_device *ndev)
 {
        struct mana_port_context *apc = netdev_priv(ndev);
+       unsigned long timeout = jiffies + 120 * HZ;
        struct gdma_dev *gd = apc->ac->gdma_dev;
        struct mana_txq *txq;
+       struct sk_buff *skb;
        int i, err;
+       u32 tsleep;
 
        if (apc->port_is_up)
                return -EINVAL;
@@ -2363,15 +2367,40 @@ static int mana_dealloc_queues(struct net_device *ndev)
         * to false, but it doesn't matter since mana_start_xmit() drops any
         * new packets due to apc->port_is_up being false.
         *
-        * Drain all the in-flight TX packets
+        * Drain all the in-flight TX packets.
+        * A timeout of 120 seconds for all the queues is used.
+        * This will break the while loop when h/w is not responding.
+        * This value of 120 has been decided here considering max
+        * number of queues.
         */
+
        for (i = 0; i < apc->num_queues; i++) {
                txq = &apc->tx_qp[i].txq;
-
-               while (atomic_read(&txq->pending_sends) > 0)
-                       usleep_range(1000, 2000);
+               tsleep = 1000;
+               while (atomic_read(&txq->pending_sends) > 0 &&
+                      time_before(jiffies, timeout)) {
+                       usleep_range(tsleep, tsleep + 1000);
+                       tsleep <<= 1;
+               }
+               if (atomic_read(&txq->pending_sends)) {
+                       err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
+                       if (err) {
+                               netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+                                          err, atomic_read(&txq->pending_sends),
+                                          txq->gdma_txq_id);
+                       }
+                       break;
+               }
        }
 
+       for (i = 0; i < apc->num_queues; i++) {
+               txq = &apc->tx_qp[i].txq;
+               while ((skb = skb_dequeue(&txq->pending_skbs))) {
+                       mana_unmap_skb(skb, apc);
+                       dev_kfree_skb_any(skb);
+               }
+               atomic_set(&txq->pending_sends, 0);
+       }
        /* We're 100% sure the queues can no longer be woken up, because
         * we're sure now mana_poll_tx_cq() can't be running.
         */
index 612b0015dc43eb261f1cc603a46aa6eed6c6f489..432fb93aa8017b11e9c83046a1cb1e0f84e83a9c 100644 (file)
@@ -1817,6 +1817,7 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
 static void ionic_tx_timeout_work(struct work_struct *ws)
 {
        struct ionic_lif *lif = container_of(ws, struct ionic_lif, tx_timeout_work);
+       int err;
 
        if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
                return;
@@ -1829,8 +1830,11 @@ static void ionic_tx_timeout_work(struct work_struct *ws)
 
        mutex_lock(&lif->queue_lock);
        ionic_stop_queues_reconfig(lif);
-       ionic_start_queues_reconfig(lif);
+       err = ionic_start_queues_reconfig(lif);
        mutex_unlock(&lif->queue_lock);
+
+       if (err)
+               dev_err(lif->ionic->dev, "%s: Restarting queues failed\n", __func__);
 }
 
 static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue)
@@ -2800,17 +2804,22 @@ static int ionic_cmb_reconfig(struct ionic_lif *lif,
                        if (err) {
                                dev_err(lif->ionic->dev,
                                        "CMB restore failed: %d\n", err);
-                               goto errout;
+                               goto err_out;
                        }
                }
 
-               ionic_start_queues_reconfig(lif);
-       } else {
-               /* This was detached in ionic_stop_queues_reconfig() */
-               netif_device_attach(lif->netdev);
+               err = ionic_start_queues_reconfig(lif);
+               if (err) {
+                       dev_err(lif->ionic->dev,
+                               "CMB reconfig failed: %d\n", err);
+                       goto err_out;
+               }
        }
 
-errout:
+err_out:
+       /* This was detached in ionic_stop_queues_reconfig() */
+       netif_device_attach(lif->netdev);
+
        return err;
 }
 
index f8682356d0cf4a22202f7704cd46359a873dffb5..94d4f9413ab7a53ce4d707b024813af9ad44d28f 100644 (file)
@@ -193,6 +193,22 @@ void qed_hw_remove(struct qed_dev *cdev);
  */
 struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn);
 
+/**
+ * qed_ptt_acquire_context(): Allocate a PTT window honoring the context
+ *                           atomicy.
+ *
+ * @p_hwfn: HW device data.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: struct qed_ptt.
+ *
+ * Should be called at the entry point to the driver
+ * (at the beginning of an exported function).
+ */
+struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn,
+                                       bool is_atomic);
+
 /**
  * qed_ptt_release(): Release PTT Window.
  *
index 3764190b948eb955fbfa996cdf3e866acfcc4edb..04602ac947087858654b7d4da206223c2dd087aa 100644 (file)
@@ -693,13 +693,14 @@ static void _qed_fcoe_get_pstats(struct qed_hwfn *p_hwfn,
 }
 
 static int qed_fcoe_get_stats(struct qed_hwfn *p_hwfn,
-                             struct qed_fcoe_stats *p_stats)
+                             struct qed_fcoe_stats *p_stats,
+                             bool is_atomic)
 {
        struct qed_ptt *p_ptt;
 
        memset(p_stats, 0, sizeof(*p_stats));
 
-       p_ptt = qed_ptt_acquire(p_hwfn);
+       p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic);
 
        if (!p_ptt) {
                DP_ERR(p_hwfn, "Failed to acquire ptt\n");
@@ -973,19 +974,27 @@ static int qed_fcoe_destroy_conn(struct qed_dev *cdev,
                                        QED_SPQ_MODE_EBLOCK, NULL);
 }
 
+static int qed_fcoe_stats_context(struct qed_dev *cdev,
+                                 struct qed_fcoe_stats *stats,
+                                 bool is_atomic)
+{
+       return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic);
+}
+
 static int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats)
 {
-       return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats);
+       return qed_fcoe_stats_context(cdev, stats, false);
 }
 
 void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
-                                struct qed_mcp_fcoe_stats *stats)
+                                struct qed_mcp_fcoe_stats *stats,
+                                bool is_atomic)
 {
        struct qed_fcoe_stats proto_stats;
 
        /* Retrieve FW statistics */
        memset(&proto_stats, 0, sizeof(proto_stats));
-       if (qed_fcoe_stats(cdev, &proto_stats)) {
+       if (qed_fcoe_stats_context(cdev, &proto_stats, is_atomic)) {
                DP_VERBOSE(cdev, QED_MSG_STORAGE,
                           "Failed to collect FCoE statistics\n");
                return;
index 19c85adf4ceb16ad029637b3c2706026937be9de..214e8299ecb4ed07ef14c8e94c9e60e001655f49 100644 (file)
@@ -28,8 +28,20 @@ int qed_fcoe_alloc(struct qed_hwfn *p_hwfn);
 void qed_fcoe_setup(struct qed_hwfn *p_hwfn);
 
 void qed_fcoe_free(struct qed_hwfn *p_hwfn);
+/**
+ * qed_get_protocol_stats_fcoe(): Fills provided statistics
+ *                               struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: Void.
+ */
 void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
-                                struct qed_mcp_fcoe_stats *stats);
+                                struct qed_mcp_fcoe_stats *stats,
+                                bool is_atomic);
 #else /* CONFIG_QED_FCOE */
 static inline int qed_fcoe_alloc(struct qed_hwfn *p_hwfn)
 {
@@ -40,7 +52,8 @@ static inline void qed_fcoe_setup(struct qed_hwfn *p_hwfn) {}
 static inline void qed_fcoe_free(struct qed_hwfn *p_hwfn) {}
 
 static inline void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
-                                              struct qed_mcp_fcoe_stats *stats)
+                                              struct qed_mcp_fcoe_stats *stats,
+                                              bool is_atomic)
 {
 }
 #endif /* CONFIG_QED_FCOE */
index 554f30b0cfd5e7c41c8dba31e503815fb929974a..6263f847b6b9265a55681e081655e171073e9170 100644 (file)
 #include "qed_reg_addr.h"
 #include "qed_sriov.h"
 
-#define QED_BAR_ACQUIRE_TIMEOUT 1000
+#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT     1000
+#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP         1000
+#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT     100000
+#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY         10
 
 /* Invalid values */
 #define QED_BAR_INVALID_OFFSET          (cpu_to_le32(-1))
@@ -84,12 +87,22 @@ void qed_ptt_pool_free(struct qed_hwfn *p_hwfn)
 }
 
 struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
+{
+       return qed_ptt_acquire_context(p_hwfn, false);
+}
+
+struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn, bool is_atomic)
 {
        struct qed_ptt *p_ptt;
-       unsigned int i;
+       unsigned int i, count;
+
+       if (is_atomic)
+               count = QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT;
+       else
+               count = QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT;
 
        /* Take the free PTT from the list */
-       for (i = 0; i < QED_BAR_ACQUIRE_TIMEOUT; i++) {
+       for (i = 0; i < count; i++) {
                spin_lock_bh(&p_hwfn->p_ptt_pool->lock);
 
                if (!list_empty(&p_hwfn->p_ptt_pool->free_list)) {
@@ -105,7 +118,12 @@ struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
                }
 
                spin_unlock_bh(&p_hwfn->p_ptt_pool->lock);
-               usleep_range(1000, 2000);
+
+               if (is_atomic)
+                       udelay(QED_BAR_ACQUIRE_TIMEOUT_UDELAY);
+               else
+                       usleep_range(QED_BAR_ACQUIRE_TIMEOUT_USLEEP,
+                                    QED_BAR_ACQUIRE_TIMEOUT_USLEEP * 2);
        }
 
        DP_NOTICE(p_hwfn, "PTT acquire timeout - failed to allocate PTT\n");
index 511ab214eb9c8af35db506c0916af665c677db94..980e7289b4814b67ad2d572242728863c270fe83 100644 (file)
@@ -999,13 +999,14 @@ static void _qed_iscsi_get_pstats(struct qed_hwfn *p_hwfn,
 }
 
 static int qed_iscsi_get_stats(struct qed_hwfn *p_hwfn,
-                              struct qed_iscsi_stats *stats)
+                              struct qed_iscsi_stats *stats,
+                              bool is_atomic)
 {
        struct qed_ptt *p_ptt;
 
        memset(stats, 0, sizeof(*stats));
 
-       p_ptt = qed_ptt_acquire(p_hwfn);
+       p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic);
        if (!p_ptt) {
                DP_ERR(p_hwfn, "Failed to acquire ptt\n");
                return -EAGAIN;
@@ -1336,9 +1337,16 @@ static int qed_iscsi_destroy_conn(struct qed_dev *cdev,
                                           QED_SPQ_MODE_EBLOCK, NULL);
 }
 
+static int qed_iscsi_stats_context(struct qed_dev *cdev,
+                                  struct qed_iscsi_stats *stats,
+                                  bool is_atomic)
+{
+       return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic);
+}
+
 static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats)
 {
-       return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats);
+       return qed_iscsi_stats_context(cdev, stats, false);
 }
 
 static int qed_iscsi_change_mac(struct qed_dev *cdev,
@@ -1358,13 +1366,14 @@ static int qed_iscsi_change_mac(struct qed_dev *cdev,
 }
 
 void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
-                                 struct qed_mcp_iscsi_stats *stats)
+                                 struct qed_mcp_iscsi_stats *stats,
+                                 bool is_atomic)
 {
        struct qed_iscsi_stats proto_stats;
 
        /* Retrieve FW statistics */
        memset(&proto_stats, 0, sizeof(proto_stats));
-       if (qed_iscsi_stats(cdev, &proto_stats)) {
+       if (qed_iscsi_stats_context(cdev, &proto_stats, is_atomic)) {
                DP_VERBOSE(cdev, QED_MSG_STORAGE,
                           "Failed to collect ISCSI statistics\n");
                return;
index dec2b00259d42d517e63d65ea042a3c8007156e1..974cb8d26608c564141029d4b87aa27a35e47837 100644 (file)
@@ -39,11 +39,14 @@ void qed_iscsi_free(struct qed_hwfn *p_hwfn);
  *
  * @cdev: Qed dev pointer.
  * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
  *
+ * Context: The function should not sleep in case is_atomic == true.
  * Return: Void.
  */
 void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
-                                 struct qed_mcp_iscsi_stats *stats);
+                                 struct qed_mcp_iscsi_stats *stats,
+                                 bool is_atomic);
 #else /* IS_ENABLED(CONFIG_QED_ISCSI) */
 static inline int qed_iscsi_alloc(struct qed_hwfn *p_hwfn)
 {
@@ -56,7 +59,8 @@ static inline void qed_iscsi_free(struct qed_hwfn *p_hwfn) {}
 
 static inline void
 qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
-                            struct qed_mcp_iscsi_stats *stats) {}
+                            struct qed_mcp_iscsi_stats *stats,
+                            bool is_atomic) {}
 #endif /* IS_ENABLED(CONFIG_QED_ISCSI) */
 
 #endif
index 7776d3bdd459a54fe3f93c0166f824c6878e50e6..970b9aabbc3d7c15362be200a3ddb71ea7661af7 100644 (file)
@@ -1863,7 +1863,8 @@ static void __qed_get_vport_stats(struct qed_hwfn *p_hwfn,
 }
 
 static void _qed_get_vport_stats(struct qed_dev *cdev,
-                                struct qed_eth_stats *stats)
+                                struct qed_eth_stats *stats,
+                                bool is_atomic)
 {
        u8 fw_vport = 0;
        int i;
@@ -1872,10 +1873,11 @@ static void _qed_get_vport_stats(struct qed_dev *cdev,
 
        for_each_hwfn(cdev, i) {
                struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
-               struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn)
-                                                   :  NULL;
+               struct qed_ptt *p_ptt;
                bool b_get_port_stats;
 
+               p_ptt = IS_PF(cdev) ? qed_ptt_acquire_context(p_hwfn, is_atomic)
+                                   : NULL;
                if (IS_PF(cdev)) {
                        /* The main vport index is relative first */
                        if (qed_fw_vport(p_hwfn, 0, &fw_vport)) {
@@ -1900,6 +1902,13 @@ out:
 }
 
 void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats)
+{
+       qed_get_vport_stats_context(cdev, stats, false);
+}
+
+void qed_get_vport_stats_context(struct qed_dev *cdev,
+                                struct qed_eth_stats *stats,
+                                bool is_atomic)
 {
        u32 i;
 
@@ -1908,7 +1917,7 @@ void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats)
                return;
        }
 
-       _qed_get_vport_stats(cdev, stats);
+       _qed_get_vport_stats(cdev, stats, is_atomic);
 
        if (!cdev->reset_stats)
                return;
@@ -1960,7 +1969,7 @@ void qed_reset_vport_stats(struct qed_dev *cdev)
        if (!cdev->reset_stats) {
                DP_INFO(cdev, "Reset stats not allocated\n");
        } else {
-               _qed_get_vport_stats(cdev, cdev->reset_stats);
+               _qed_get_vport_stats(cdev, cdev->reset_stats, false);
                cdev->reset_stats->common.link_change_count = 0;
        }
 }
index a538cf478c14e733ac8f7777205499bd34eccf30..2d2f82c785ad2e0085d809328cb6e1a51144dc87 100644 (file)
@@ -249,8 +249,32 @@ qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
                            enum spq_mode comp_mode,
                            struct qed_spq_comp_cb *p_comp_data);
 
+/**
+ * qed_get_vport_stats(): Fills provided statistics
+ *                       struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ *
+ * Return: Void.
+ */
 void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats);
 
+/**
+ * qed_get_vport_stats_context(): Fills provided statistics
+ *                               struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: Void.
+ */
+void qed_get_vport_stats_context(struct qed_dev *cdev,
+                                struct qed_eth_stats *stats,
+                                bool is_atomic);
+
 void qed_reset_vport_stats(struct qed_dev *cdev);
 
 /**
index f5af83342856fdb5de0a86ca8c26d09b990dd50d..c278f8893042b3a88466452cd205348aebac609c 100644 (file)
@@ -3092,7 +3092,7 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
 
        switch (type) {
        case QED_MCP_LAN_STATS:
-               qed_get_vport_stats(cdev, &eth_stats);
+               qed_get_vport_stats_context(cdev, &eth_stats, true);
                stats->lan_stats.ucast_rx_pkts =
                                        eth_stats.common.rx_ucast_pkts;
                stats->lan_stats.ucast_tx_pkts =
@@ -3100,10 +3100,10 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
                stats->lan_stats.fcs_err = -1;
                break;
        case QED_MCP_FCOE_STATS:
-               qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats);
+               qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats, true);
                break;
        case QED_MCP_ISCSI_STATS:
-               qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats);
+               qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats, true);
                break;
        default:
                DP_VERBOSE(cdev, QED_MSG_SP,
index 4b004a7281903fe72e351ee2a5a22bc1c52a731e..99df00c30b8c6cc3b297571d5fb059bd86712e1c 100644 (file)
@@ -176,6 +176,15 @@ static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param)
 }
 #endif
 
+static int __maybe_unused qede_suspend(struct device *dev)
+{
+       dev_info(dev, "Device does not support suspend operation\n");
+
+       return -EOPNOTSUPP;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(qede_pm_ops, qede_suspend, NULL);
+
 static const struct pci_error_handlers qede_err_handler = {
        .error_detected = qede_io_error_detected,
 };
@@ -190,6 +199,7 @@ static struct pci_driver qede_pci_driver = {
        .sriov_configure = qede_sriov_configure,
 #endif
        .err_handler = &qede_err_handler,
+       .driver.pm = &qede_pm_ops,
 };
 
 static struct qed_eth_cb_ops qede_ll_ops = {
index 7adde9639c8aba091396236db1aa888241042ba7..35d8e9811998d94e7a6baaedb721f8c518c5b9d6 100644 (file)
@@ -1194,7 +1194,7 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
                net_dev->features |= NETIF_F_HW_TC;
                efx->fixed_features |= NETIF_F_HW_TC;
        }
-       return rc;
+       return 0;
 }
 
 int ef100_probe_vf(struct efx_nic *efx)
index 9e5ce2a13787ab0ef95fc1f3a5f98763fee79d6c..cf1d67b6d86db52eb2b0bc8bbd36591b85f0dabf 100644 (file)
  */
 struct ef4_loopback_payload {
        char pad[2]; /* Ensures ip is 4-byte aligned */
-       struct ethhdr header;
-       struct iphdr ip;
-       struct udphdr udp;
-       __be16 iteration;
-       char msg[64];
+       struct_group_attr(packet, __packed,
+               struct ethhdr header;
+               struct iphdr ip;
+               struct udphdr udp;
+               __be16 iteration;
+               char msg[64];
+       );
 } __packed __aligned(4);
-#define EF4_LOOPBACK_PAYLOAD_LEN       (sizeof(struct ef4_loopback_payload) - \
-                                        offsetof(struct ef4_loopback_payload, \
-                                                 header))
+#define EF4_LOOPBACK_PAYLOAD_LEN       \
+               sizeof_field(struct ef4_loopback_payload, packet)
 
 /* Loopback test source MAC address */
 static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -299,7 +300,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
 
        payload = &state->payload;
 
-       memcpy(&received.header, buf_ptr,
+       memcpy(&received.packet, buf_ptr,
               min_t(int, pkt_len, EF4_LOOPBACK_PAYLOAD_LEN));
        received.ip.saddr = payload->ip.saddr;
        if (state->offload_csum)
@@ -370,7 +371,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
                               buf_ptr, pkt_len, 0);
                netif_err(efx, drv, efx->net_dev, "expected packet:\n");
                print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
-                              &state->payload.header, EF4_LOOPBACK_PAYLOAD_LEN,
+                              &state->payload.packet, EF4_LOOPBACK_PAYLOAD_LEN,
                               0);
        }
 #endif
@@ -440,6 +441,8 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue)
                payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
                /* Strip off the leading padding */
                skb_pull(skb, offsetof(struct ef4_loopback_payload, header));
+               /* Strip off the trailing padding */
+               skb_trim(skb, EF4_LOOPBACK_PAYLOAD_LEN);
 
                /* Ensure everything we've written is visible to the
                 * interrupt handler. */
index 96d856b9043c4ce6c78b6c2716de3e6b4bd4b4a2..19a0b8584afbb8f3fca52d6adf06f61445d0579b 100644 (file)
  */
 struct efx_loopback_payload {
        char pad[2]; /* Ensures ip is 4-byte aligned */
-       struct ethhdr header;
-       struct iphdr ip;
-       struct udphdr udp;
-       __be16 iteration;
-       char msg[64];
+       struct_group_attr(packet, __packed,
+               struct ethhdr header;
+               struct iphdr ip;
+               struct udphdr udp;
+               __be16 iteration;
+               char msg[64];
+       );
 } __packed __aligned(4);
-#define EFX_LOOPBACK_PAYLOAD_LEN       (sizeof(struct efx_loopback_payload) - \
-                                        offsetof(struct efx_loopback_payload, \
-                                                 header))
+#define EFX_LOOPBACK_PAYLOAD_LEN       \
+               sizeof_field(struct efx_loopback_payload, packet)
 
 /* Loopback test source MAC address */
 static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -297,7 +298,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
 
        payload = &state->payload;
 
-       memcpy(&received.header, buf_ptr,
+       memcpy(&received.packet, buf_ptr,
               min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN));
        received.ip.saddr = payload->ip.saddr;
        if (state->offload_csum)
@@ -368,7 +369,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
                               buf_ptr, pkt_len, 0);
                netif_err(efx, drv, efx->net_dev, "expected packet:\n");
                print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
-                              &state->payload.header, EFX_LOOPBACK_PAYLOAD_LEN,
+                              &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN,
                               0);
        }
 #endif
@@ -438,6 +439,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
                payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
                /* Strip off the leading padding */
                skb_pull(skb, offsetof(struct efx_loopback_payload, header));
+               /* Strip off the trailing padding */
+               skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN);
 
                /* Ensure everything we've written is visible to the
                 * interrupt handler. */
index 111ac17194a5637ceb279e12edf460491b27071f..b55fd33469727d2a568804e00aad063567574662 100644 (file)
  */
 struct efx_loopback_payload {
        char pad[2]; /* Ensures ip is 4-byte aligned */
-       struct ethhdr header;
-       struct iphdr ip;
-       struct udphdr udp;
-       __be16 iteration;
-       char msg[64];
+       struct_group_attr(packet, __packed,
+               struct ethhdr header;
+               struct iphdr ip;
+               struct udphdr udp;
+               __be16 iteration;
+               char msg[64];
+       );
 } __packed __aligned(4);
-#define EFX_LOOPBACK_PAYLOAD_LEN       (sizeof(struct efx_loopback_payload) - \
-                                        offsetof(struct efx_loopback_payload, \
-                                                 header))
+#define EFX_LOOPBACK_PAYLOAD_LEN       \
+               sizeof_field(struct efx_loopback_payload, packet)
 
 /* Loopback test source MAC address */
 static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -297,7 +298,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
 
        payload = &state->payload;
 
-       memcpy(&received.header, buf_ptr,
+       memcpy(&received.packet, buf_ptr,
               min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN));
        received.ip.saddr = payload->ip.saddr;
        if (state->offload_csum)
@@ -368,7 +369,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
                               buf_ptr, pkt_len, 0);
                netif_err(efx, drv, efx->net_dev, "expected packet:\n");
                print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
-                              &state->payload.header, EFX_LOOPBACK_PAYLOAD_LEN,
+                              &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN,
                               0);
        }
 #endif
@@ -438,6 +439,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
                payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
                /* Strip off the leading padding */
                skb_pull(skb, offsetof(struct efx_loopback_payload, header));
+               /* Strip off the trailing padding */
+               skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN);
 
                /* Ensure everything we've written is visible to the
                 * interrupt handler. */
index 15ebd39739224fdb7d87df83048c8a8b11775f1f..fe268b6c1cacf5ff1a3689f0fd7e72045d9f5906 100644 (file)
@@ -1657,10 +1657,10 @@ int efx_init_tc(struct efx_nic *efx)
        rc = efx_tc_configure_fallback_acts_reps(efx);
        if (rc)
                return rc;
-       efx->tc->up = true;
        rc = flow_indr_dev_register(efx_tc_indr_setup_cb, efx);
        if (rc)
                return rc;
+       efx->tc->up = true;
        return 0;
 }
 
index 2d7347b71c41b238fc5b905f13157f3a521be53c..0dcd6a568b061242f510dd460dde5798895ab1a5 100644 (file)
@@ -1851,6 +1851,17 @@ static int netsec_of_probe(struct platform_device *pdev,
                return err;
        }
 
+       /*
+        * SynQuacer is physically configured with TX and RX delays
+        * but the standard firmware claimed otherwise for a long
+        * time, ignore it.
+        */
+       if (of_machine_is_compatible("socionext,developer-box") &&
+           priv->phy_interface != PHY_INTERFACE_MODE_RGMII_ID) {
+               dev_warn(&pdev->dev, "Outdated firmware reports incorrect PHY mode, overriding\n");
+               priv->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
+       }
+
        priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
        if (!priv->phy_np) {
                dev_err(&pdev->dev, "missing required property 'phy-handle'\n");
index f8367c5b490baa64d01ac753ed5abf733defbab8..fbb0ccf84afc46727ee013cad7fc684300c96453 100644 (file)
@@ -234,7 +234,8 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
        res.addr = mgbe->regs;
        res.irq = irq;
 
-       mgbe->clks = devm_kzalloc(&pdev->dev, sizeof(*mgbe->clks), GFP_KERNEL);
+       mgbe->clks = devm_kcalloc(&pdev->dev, ARRAY_SIZE(mgbe_clks),
+                                 sizeof(*mgbe->clks), GFP_KERNEL);
        if (!mgbe->clks)
                return -ENOMEM;
 
index e0ac1bcd9925c2ebfe122ff1faf9a40479a0afdb..49f303353ecb088a826ec537b47dfff320070b6e 100644 (file)
@@ -1567,12 +1567,16 @@ static int temac_probe(struct platform_device *pdev)
        }
 
        /* Error handle returned DMA RX and TX interrupts */
-       if (lp->rx_irq < 0)
-               return dev_err_probe(&pdev->dev, lp->rx_irq,
+       if (lp->rx_irq <= 0) {
+               rc = lp->rx_irq ?: -EINVAL;
+               return dev_err_probe(&pdev->dev, rc,
                                     "could not get DMA RX irq\n");
-       if (lp->tx_irq < 0)
-               return dev_err_probe(&pdev->dev, lp->tx_irq,
+       }
+       if (lp->tx_irq <= 0) {
+               rc = lp->tx_irq ?: -EINVAL;
+               return dev_err_probe(&pdev->dev, rc,
                                     "could not get DMA TX irq\n");
+       }
 
        if (temac_np) {
                /* Retrieve the MAC address */
index 984dfa5d6c11cb3ae6900597edeb1612f27decc3..144ec756c796a6962286b69cbabe223ad4984610 100644 (file)
@@ -743,7 +743,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u
                u64_stats_update_begin(&rxsc_stats->syncp);
                rxsc_stats->stats.InPktsLate++;
                u64_stats_update_end(&rxsc_stats->syncp);
-               secy->netdev->stats.rx_dropped++;
+               DEV_STATS_INC(secy->netdev, rx_dropped);
                return false;
        }
 
@@ -767,7 +767,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u
                        rxsc_stats->stats.InPktsNotValid++;
                        u64_stats_update_end(&rxsc_stats->syncp);
                        this_cpu_inc(rx_sa->stats->InPktsNotValid);
-                       secy->netdev->stats.rx_errors++;
+                       DEV_STATS_INC(secy->netdev, rx_errors);
                        return false;
                }
 
@@ -1069,7 +1069,7 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
                        u64_stats_update_begin(&secy_stats->syncp);
                        secy_stats->stats.InPktsNoTag++;
                        u64_stats_update_end(&secy_stats->syncp);
-                       macsec->secy.netdev->stats.rx_dropped++;
+                       DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
                        continue;
                }
 
@@ -1179,7 +1179,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
                u64_stats_update_begin(&secy_stats->syncp);
                secy_stats->stats.InPktsBadTag++;
                u64_stats_update_end(&secy_stats->syncp);
-               secy->netdev->stats.rx_errors++;
+               DEV_STATS_INC(secy->netdev, rx_errors);
                goto drop_nosa;
        }
 
@@ -1196,7 +1196,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
                        u64_stats_update_begin(&rxsc_stats->syncp);
                        rxsc_stats->stats.InPktsNotUsingSA++;
                        u64_stats_update_end(&rxsc_stats->syncp);
-                       secy->netdev->stats.rx_errors++;
+                       DEV_STATS_INC(secy->netdev, rx_errors);
                        if (active_rx_sa)
                                this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA);
                        goto drop_nosa;
@@ -1230,7 +1230,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
                        u64_stats_update_begin(&rxsc_stats->syncp);
                        rxsc_stats->stats.InPktsLate++;
                        u64_stats_update_end(&rxsc_stats->syncp);
-                       macsec->secy.netdev->stats.rx_dropped++;
+                       DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
                        goto drop;
                }
        }
@@ -1271,7 +1271,7 @@ deliver:
        if (ret == NET_RX_SUCCESS)
                count_rx(dev, len);
        else
-               macsec->secy.netdev->stats.rx_dropped++;
+               DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
 
        rcu_read_unlock();
 
@@ -1308,7 +1308,7 @@ nosci:
                        u64_stats_update_begin(&secy_stats->syncp);
                        secy_stats->stats.InPktsNoSCI++;
                        u64_stats_update_end(&secy_stats->syncp);
-                       macsec->secy.netdev->stats.rx_errors++;
+                       DEV_STATS_INC(macsec->secy.netdev, rx_errors);
                        continue;
                }
 
@@ -1327,7 +1327,7 @@ nosci:
                        secy_stats->stats.InPktsUnknownSCI++;
                        u64_stats_update_end(&secy_stats->syncp);
                } else {
-                       macsec->secy.netdev->stats.rx_dropped++;
+                       DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
                }
        }
 
@@ -3422,7 +3422,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
 
        if (!secy->operational) {
                kfree_skb(skb);
-               dev->stats.tx_dropped++;
+               DEV_STATS_INC(dev, tx_dropped);
                return NETDEV_TX_OK;
        }
 
@@ -3430,7 +3430,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
        skb = macsec_encrypt(skb, dev);
        if (IS_ERR(skb)) {
                if (PTR_ERR(skb) != -EINPROGRESS)
-                       dev->stats.tx_dropped++;
+                       DEV_STATS_INC(dev, tx_dropped);
                return NETDEV_TX_OK;
        }
 
@@ -3667,9 +3667,9 @@ static void macsec_get_stats64(struct net_device *dev,
 
        dev_fetch_sw_netstats(s, dev->tstats);
 
-       s->rx_dropped = dev->stats.rx_dropped;
-       s->tx_dropped = dev->stats.tx_dropped;
-       s->rx_errors = dev->stats.rx_errors;
+       s->rx_dropped = atomic_long_read(&dev->stats.__rx_dropped);
+       s->tx_dropped = atomic_long_read(&dev->stats.__tx_dropped);
+       s->rx_errors = atomic_long_read(&dev->stats.__rx_errors);
 }
 
 static int macsec_get_iflink(const struct net_device *dev)
index 323bec5e57f83e435c629e18fae23ef5b2d1528b..356099169003878ea82e254f8f0743eeababdd89 100644 (file)
@@ -313,15 +313,21 @@ struct phylink_pcs *miic_create(struct device *dev, struct device_node *np)
 
        pdev = of_find_device_by_node(pcs_np);
        of_node_put(pcs_np);
-       if (!pdev || !platform_get_drvdata(pdev))
+       if (!pdev || !platform_get_drvdata(pdev)) {
+               if (pdev)
+                       put_device(&pdev->dev);
                return ERR_PTR(-EPROBE_DEFER);
+       }
 
        miic_port = kzalloc(sizeof(*miic_port), GFP_KERNEL);
-       if (!miic_port)
+       if (!miic_port) {
+               put_device(&pdev->dev);
                return ERR_PTR(-ENOMEM);
+       }
 
        miic = platform_get_drvdata(pdev);
        device_link_add(dev, miic->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+       put_device(&pdev->dev);
 
        miic_port->miic = miic;
        miic_port->port = port - 1;
index c1f307d90518b93f992fdce7d50b66a4c1edc433..8a77ec33b4172ca2acd2029f65664d8480f58fd2 100644 (file)
@@ -459,21 +459,27 @@ static int at803x_set_wol(struct phy_device *phydev,
                        phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i],
                                      mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
 
-               /* Enable WOL function */
-               ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL,
-                               0, AT803X_WOL_EN);
-               if (ret)
-                       return ret;
+               /* Enable WOL function for 1588 */
+               if (phydev->drv->phy_id == ATH8031_PHY_ID) {
+                       ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+                                            AT803X_PHY_MMD3_WOL_CTRL,
+                                            0, AT803X_WOL_EN);
+                       if (ret)
+                               return ret;
+               }
                /* Enable WOL interrupt */
                ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
                if (ret)
                        return ret;
        } else {
-               /* Disable WoL function */
-               ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL,
-                               AT803X_WOL_EN, 0);
-               if (ret)
-                       return ret;
+               /* Disable WoL function for 1588 */
+               if (phydev->drv->phy_id == ATH8031_PHY_ID) {
+                       ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+                                            AT803X_PHY_MMD3_WOL_CTRL,
+                                            AT803X_WOL_EN, 0);
+                       if (ret)
+                               return ret;
+               }
                /* Disable WOL interrupt */
                ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
                if (ret)
@@ -508,11 +514,11 @@ static void at803x_get_wol(struct phy_device *phydev,
        wol->supported = WAKE_MAGIC;
        wol->wolopts = 0;
 
-       value = phy_read_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL);
+       value = phy_read(phydev, AT803X_INTR_ENABLE);
        if (value < 0)
                return;
 
-       if (value & AT803X_WOL_EN)
+       if (value & AT803X_INTR_ENABLE_WOL)
                wol->wolopts |= WAKE_MAGIC;
 }
 
@@ -858,9 +864,6 @@ static int at803x_probe(struct phy_device *phydev)
        if (phydev->drv->phy_id == ATH8031_PHY_ID) {
                int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
                int mode_cfg;
-               struct ethtool_wolinfo wol = {
-                       .wolopts = 0,
-               };
 
                if (ccr < 0)
                        return ccr;
@@ -877,12 +880,14 @@ static int at803x_probe(struct phy_device *phydev)
                        break;
                }
 
-               /* Disable WOL by default */
-               ret = at803x_set_wol(phydev, &wol);
-               if (ret < 0) {
-                       phydev_err(phydev, "failed to disable WOL on probe: %d\n", ret);
+               /* Disable WoL in 1588 register which is enabled
+                * by default
+                */
+               ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+                                    AT803X_PHY_MMD3_WOL_CTRL,
+                                    AT803X_WOL_EN, 0);
+               if (ret)
                        return ret;
-               }
        }
 
        return 0;
@@ -2059,8 +2064,6 @@ static struct phy_driver at803x_driver[] = {
        .flags                  = PHY_POLL_CABLE_TEST,
        .config_init            = at803x_config_init,
        .link_change_notify     = at803x_link_change_notify,
-       .set_wol                = at803x_set_wol,
-       .get_wol                = at803x_get_wol,
        .suspend                = at803x_suspend,
        .resume                 = at803x_resume,
        /* PHY_BASIC_FEATURES */
index 59cae0d808aa2ec33537a1a5c5ddf9182e894a1c..04b2e6eeb1952233a36f9fe0324073388d3951c2 100644 (file)
@@ -542,6 +542,17 @@ static int bcm54xx_resume(struct phy_device *phydev)
        return bcm54xx_config_init(phydev);
 }
 
+static int bcm54810_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
+{
+       return -EOPNOTSUPP;
+}
+
+static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
+                             u16 val)
+{
+       return -EOPNOTSUPP;
+}
+
 static int bcm54811_config_init(struct phy_device *phydev)
 {
        int err, reg;
@@ -1103,6 +1114,8 @@ static struct phy_driver broadcom_drivers[] = {
        .get_strings    = bcm_phy_get_strings,
        .get_stats      = bcm54xx_get_stats,
        .probe          = bcm54xx_phy_probe,
+       .read_mmd       = bcm54810_read_mmd,
+       .write_mmd      = bcm54810_write_mmd,
        .config_init    = bcm54xx_config_init,
        .config_aneg    = bcm5481_config_aneg,
        .config_intr    = bcm_phy_config_intr,
index 61921d4dbb13a82985091accfa943bba021fb71f..c7cf61fe41cf7be3749f9865bf72df971c60c7ba 100644 (file)
@@ -3216,6 +3216,8 @@ static int phy_probe(struct device *dev)
                        goto out;
        }
 
+       phy_disable_interrupts(phydev);
+
        /* Start out supporting everything. Eventually,
         * a controller will attach, and may modify one
         * or both of these values
@@ -3333,16 +3335,6 @@ static int phy_remove(struct device *dev)
        return 0;
 }
 
-static void phy_shutdown(struct device *dev)
-{
-       struct phy_device *phydev = to_phy_device(dev);
-
-       if (phydev->state == PHY_READY || !phydev->attached_dev)
-               return;
-
-       phy_disable_interrupts(phydev);
-}
-
 /**
  * phy_driver_register - register a phy_driver with the PHY layer
  * @new_driver: new phy_driver to register
@@ -3376,7 +3368,6 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
        new_driver->mdiodrv.driver.bus = &mdio_bus_type;
        new_driver->mdiodrv.driver.probe = phy_probe;
        new_driver->mdiodrv.driver.remove = phy_remove;
-       new_driver->mdiodrv.driver.shutdown = phy_shutdown;
        new_driver->mdiodrv.driver.owner = owner;
        new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS;
 
index 9137fb8c1c420a792211cb70105144e8c2d73bc9..49d1d6acf95eb9c2eafa8b1613fc6b90cb7e80b2 100644 (file)
@@ -534,7 +534,7 @@ static int tap_open(struct inode *inode, struct file *file)
        q->sock.state = SS_CONNECTED;
        q->sock.file = file;
        q->sock.ops = &tap_socket_ops;
-       sock_init_data_uid(&q->sock, &q->sk, inode->i_uid);
+       sock_init_data_uid(&q->sock, &q->sk, current_fsuid());
        q->sk.sk_write_space = tap_sock_write_space;
        q->sk.sk_destruct = tap_sock_destruct;
        q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
index d3dc22509ea582644474c943361bdb1b48076503..382756c3fb837a97bf0e9e8a0ddad60347ae70e8 100644 (file)
@@ -2200,7 +2200,9 @@ static void team_setup(struct net_device *dev)
 
        dev->hw_features = TEAM_VLAN_FEATURES |
                           NETIF_F_HW_VLAN_CTAG_RX |
-                          NETIF_F_HW_VLAN_CTAG_FILTER;
+                          NETIF_F_HW_VLAN_CTAG_FILTER |
+                          NETIF_F_HW_VLAN_STAG_RX |
+                          NETIF_F_HW_VLAN_STAG_FILTER;
 
        dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
        dev->features |= dev->hw_features;
index d75456adc62ac82a4f9da10c50c48266c5a9a0c0..100339bc8b04a10cd5044f9a392cdaddc105ee0d 100644 (file)
@@ -1594,7 +1594,7 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile,
        if (zerocopy)
                return false;
 
-       if (SKB_DATA_ALIGN(len + TUN_RX_PAD) +
+       if (SKB_DATA_ALIGN(len + TUN_RX_PAD + XDP_PACKET_HEADROOM) +
            SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PAGE_SIZE)
                return false;
 
@@ -3469,7 +3469,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
        tfile->socket.file = file;
        tfile->socket.ops = &tun_socket_ops;
 
-       sock_init_data_uid(&tfile->socket, &tfile->sk, inode->i_uid);
+       sock_init_data_uid(&tfile->socket, &tfile->sk, current_fsuid());
 
        tfile->sk.sk_write_space = tun_sock_write_space;
        tfile->sk.sk_sndbuf = INT_MAX;
index c00a89b24df969466236e8ec1251b44a4718adfa..6d61052353f078e41cdb53b2fcb07bf900a4768c 100644 (file)
@@ -618,9 +618,23 @@ static const struct usb_device_id  products[] = {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                          | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
+       .idProduct              = 0x8005,   /* A-300 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info        = 0,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
        .idProduct              = 0x8006,       /* B-500/SL-5600 */
        ZAURUS_MASTER_INTERFACE,
        .driver_info            = 0,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
+       .idProduct              = 0x8006,   /* B-500/SL-5600 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info        = 0,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                          | USB_DEVICE_ID_MATCH_DEVICE,
@@ -628,6 +642,13 @@ static const struct usb_device_id  products[] = {
        .idProduct              = 0x8007,       /* C-700 */
        ZAURUS_MASTER_INTERFACE,
        .driver_info            = 0,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
+       .idProduct              = 0x8007,   /* C-700 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info        = 0,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                 | USB_DEVICE_ID_MATCH_DEVICE,
index c458c030fadf6cbaa7a55a4e35344bf2a01122a4..59cde06aa7f60c8ca71eace64907417a6f5d59ff 100644 (file)
@@ -4224,8 +4224,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
        if (!dev)
                return;
 
-       set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
-
        netif_napi_del(&dev->napi);
 
        udev = interface_to_usbdev(intf);
@@ -4233,6 +4231,8 @@ static void lan78xx_disconnect(struct usb_interface *intf)
 
        unregister_netdev(net);
 
+       timer_shutdown_sync(&dev->stat_monitor);
+       set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
        cancel_delayed_work_sync(&dev->wq);
 
        phydev = net->phydev;
@@ -4247,9 +4247,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
 
        usb_scuttle_anchored_urbs(&dev->deferred);
 
-       if (timer_pending(&dev->stat_monitor))
-               del_timer_sync(&dev->stat_monitor);
-
        lan78xx_unbind(dev, intf);
 
        lan78xx_free_tx_resources(dev);
index 417f7ea1fffa692bd3ef274a942670fc53700d3c..344af3c5c836683db6e1183214391353df0009d3 100644 (file)
@@ -1423,6 +1423,7 @@ static const struct usb_device_id products[] = {
        {QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */
        {QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */
        {QMI_FIXED_INTF(0x2c7c, 0x0296, 4)},    /* Quectel BG96 */
+       {QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)}, /* Quectel EM05GV2 */
        {QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */
        {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)},    /* Foxconn T77W968 LTE */
        {QMI_FIXED_INTF(0x0489, 0xe0b5, 0)},    /* Foxconn T77W968 LTE with eSIM support*/
index 7984f2157d222dbe2971702221dac46b2a370721..df3617c4c44e8ff41b2736f5ac6188b02ca3f92e 100644 (file)
@@ -289,9 +289,23 @@ static const struct usb_device_id  products [] = {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                          | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
+       .idProduct              = 0x8005,       /* A-300 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
        .idProduct              = 0x8006,       /* B-500/SL-5600 */
        ZAURUS_MASTER_INTERFACE,
        .driver_info = ZAURUS_PXA_INFO,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
+       .idProduct              = 0x8006,       /* B-500/SL-5600 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info = (unsigned long)&bogus_mdlm_info,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                  | USB_DEVICE_ID_MATCH_DEVICE,
@@ -299,6 +313,13 @@ static const struct usb_device_id  products [] = {
        .idProduct              = 0x8007,       /* C-700 */
        ZAURUS_MASTER_INTERFACE,
        .driver_info = ZAURUS_PXA_INFO,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
+       .idProduct              = 0x8007,       /* C-700 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info = (unsigned long)&bogus_mdlm_info,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                 | USB_DEVICE_ID_MATCH_DEVICE,
index 614f3e3efab0950fa4bbe1ee897ba008fc5e3369..509e901da41dbb351c317d49a0f72eb0bff76496 100644 (file)
@@ -1081,8 +1081,9 @@ static int __veth_napi_enable_range(struct net_device *dev, int start, int end)
 err_xdp_ring:
        for (i--; i >= start; i--)
                ptr_ring_cleanup(&priv->rq[i].xdp_ring, veth_ptr_free);
+       i = end;
 err_page_pool:
-       for (i = start; i < end; i++) {
+       for (i--; i >= start; i--) {
                page_pool_destroy(priv->rq[i].page_pool);
                priv->rq[i].page_pool = NULL;
        }
index 1270c8d23463fa35849dd290b7df7496198aaf9b..8e9f4cfe941f63a64a5bb3742534b84e0e15f1e9 100644 (file)
@@ -2761,7 +2761,7 @@ static void virtnet_init_default_rss(struct virtnet_info *vi)
                vi->ctrl->rss.indirection_table[i] = indir_val;
        }
 
-       vi->ctrl->rss.max_tx_vq = vi->curr_queue_pairs;
+       vi->ctrl->rss.max_tx_vq = vi->has_rss ? vi->curr_queue_pairs : 0;
        vi->ctrl->rss.hash_key_length = vi->rss_key_size;
 
        netdev_rss_key_fill(vi->ctrl->rss.key, vi->rss_key_size);
@@ -4219,8 +4219,6 @@ static int virtnet_probe(struct virtio_device *vdev)
        if (vi->has_rss || vi->has_rss_hash_report)
                virtnet_init_default_rss(vi);
 
-       _virtnet_set_queues(vi, vi->curr_queue_pairs);
-
        /* serialize netdev register + virtio_device_ready() with ndo_open() */
        rtnl_lock();
 
@@ -4233,6 +4231,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 
        virtio_device_ready(vdev);
 
+       _virtnet_set_queues(vi, vi->curr_queue_pairs);
+
        /* a random MAC address has been assigned, notify the device.
         * We don't fail probe if VIRTIO_NET_F_CTRL_MAC_ADDR is not there
         * because many devices work fine without getting MAC explicitly
index a3de081cda5ee15b1f531363f61d016d4ac7dce3..c3ff30ab782e942cd679a6b8c7a950c4a3488753 100644 (file)
@@ -713,6 +713,12 @@ static struct vxlan_vni_node *vxlan_vni_alloc(struct vxlan_dev *vxlan,
        return vninode;
 }
 
+static void vxlan_vni_free(struct vxlan_vni_node *vninode)
+{
+       free_percpu(vninode->stats);
+       kfree(vninode);
+}
+
 static int vxlan_vni_add(struct vxlan_dev *vxlan,
                         struct vxlan_vni_group *vg,
                         u32 vni, union vxlan_addr *group,
@@ -740,7 +746,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan,
                                            &vninode->vnode,
                                            vxlan_vni_rht_params);
        if (err) {
-               kfree(vninode);
+               vxlan_vni_free(vninode);
                return err;
        }
 
@@ -763,8 +769,7 @@ static void vxlan_vni_node_rcu_free(struct rcu_head *rcu)
        struct vxlan_vni_node *v;
 
        v = container_of(rcu, struct vxlan_vni_node, rcu);
-       free_percpu(v->stats);
-       kfree(v);
+       vxlan_vni_free(v);
 }
 
 static int vxlan_vni_del(struct vxlan_dev *vxlan,
index 5bf7822c53f18ab75f1b256a3e64ab14f161c825..0ba714ca5185cd94124bd121a49117b79b9898bc 100644 (file)
@@ -6,7 +6,7 @@
 #include "allowedips.h"
 #include "peer.h"
 
-enum { MAX_ALLOWEDIPS_BITS = 128 };
+enum { MAX_ALLOWEDIPS_DEPTH = 129 };
 
 static struct kmem_cache *node_cache;
 
@@ -42,7 +42,7 @@ static void push_rcu(struct allowedips_node **stack,
                     struct allowedips_node __rcu *p, unsigned int *len)
 {
        if (rcu_access_pointer(p)) {
-               if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_BITS))
+               if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_DEPTH))
                        return;
                stack[(*len)++] = rcu_dereference_raw(p);
        }
@@ -55,7 +55,7 @@ static void node_free_rcu(struct rcu_head *rcu)
 
 static void root_free_rcu(struct rcu_head *rcu)
 {
-       struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = {
+       struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = {
                container_of(rcu, struct allowedips_node, rcu) };
        unsigned int len = 1;
 
@@ -68,7 +68,7 @@ static void root_free_rcu(struct rcu_head *rcu)
 
 static void root_remove_peer_lists(struct allowedips_node *root)
 {
-       struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = { root };
+       struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = { root };
        unsigned int len = 1;
 
        while (len > 0 && (node = stack[--len])) {
index 78ebe2892a7886ca21c34c2fd7bab1be3024948f..3d1f64ff2e1225aea957f24c08b05e859956dc6f 100644 (file)
@@ -593,16 +593,20 @@ bool __init wg_allowedips_selftest(void)
        wg_allowedips_remove_by_peer(&t, a, &mutex);
        test_negative(4, a, 192, 168, 0, 1);
 
-       /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_BITS) in free_node
+       /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_DEPTH) in free_node
         * if something goes wrong.
         */
-       for (i = 0; i < MAX_ALLOWEDIPS_BITS; ++i) {
-               part = cpu_to_be64(~(1LLU << (i % 64)));
-               memset(&ip, 0xff, 16);
-               memcpy((u8 *)&ip + (i < 64) * 8, &part, 8);
+       for (i = 0; i < 64; ++i) {
+               part = cpu_to_be64(~0LLU << i);
+               memset(&ip, 0xff, 8);
+               memcpy((u8 *)&ip + 8, &part, 8);
+               wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
+               memcpy(&ip, &part, 8);
+               memset((u8 *)&ip + 8, 0, 8);
                wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
        }
-
+       memset(&ip, 0, 16);
+       wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
        wg_allowedips_free(&t, &mutex);
 
        wg_allowedips_init(&t);
index 1cebba7889d78d40e055c5e1f34ae9fcfccfbc2a..139da578831a44885baf050fd6b8709681bf88f7 100644 (file)
@@ -376,7 +376,6 @@ static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
                struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
 
                if (!irq_grp->napi_enabled) {
-                       dev_set_threaded(&irq_grp->napi_ndev, true);
                        napi_enable(&irq_grp->napi);
                        irq_grp->napi_enabled = true;
                }
index c899616fbee4b55a52cc1099ed5892021876f854..c63083633b3713605f619e054dd3082e3e96556b 100644 (file)
@@ -466,7 +466,6 @@ void ath11k_pcic_ext_irq_enable(struct ath11k_base *ab)
                struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
 
                if (!irq_grp->napi_enabled) {
-                       dev_set_threaded(&irq_grp->napi_ndev, true);
                        napi_enable(&irq_grp->napi);
                        irq_grp->napi_enabled = true;
                }
index 6512267ae4ca5d936be6f0cfe7d83abbc8273318..4928e4e91660357c2db8c3921778bcaeff8d651f 100644 (file)
@@ -2144,8 +2144,7 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
        struct wmi_tlv *tlv;
        void *ptr;
        int i, ret, len;
-       u32 *tmp_ptr;
-       u8 extraie_len_with_pad = 0;
+       u32 *tmp_ptr, extraie_len_with_pad = 0;
        struct ath12k_wmi_hint_short_ssid_arg *s_ssid = NULL;
        struct ath12k_wmi_hint_bssid_arg *hint_bssid = NULL;
 
index a75bfa9fd1cfd0c2b81bffa5433f6b18382c2059..dc2b3b46781e190a59558b41d8cbd87b3e409df6 100644 (file)
@@ -36,11 +36,6 @@ ath6kl_core-y += wmi.o
 ath6kl_core-y += core.o
 ath6kl_core-y += recovery.o
 
-# FIXME: temporarily silence -Wdangling-pointer on non W=1+ builds
-ifndef KBUILD_EXTRA_WARN
-CFLAGS_htc_mbox.o += $(call cc-disable-warning, dangling-pointer)
-endif
-
 ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
 ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o
 
index de8a2e27f49c7301d54ac8c6746040c51c34e847..2a90bb24ba77f90e06b332cb7c31c94ece860dd6 100644 (file)
@@ -1456,6 +1456,10 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
                params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
                params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE;
                params_v1 = kzalloc(params_size, GFP_KERNEL);
+               if (!params_v1) {
+                       err = -ENOMEM;
+                       goto exit_params;
+               }
                params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
                brcmf_scan_params_v2_to_v1(&params->params_v2_le, &params_v1->params_le);
                kfree(params);
@@ -1473,6 +1477,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
                        bphy_err(drvr, "error (%d)\n", err);
        }
 
+exit_params:
        kfree(params);
 exit:
        return err;
index 792adaf880b4448451b7a50bba0732bfdedcc961..bece26741d3a350a6e6eb08bf80c1478a4781751 100644 (file)
@@ -398,7 +398,12 @@ struct brcmf_scan_params_le {
                                 * fixed parameter portion is assumed, otherwise
                                 * ssid in the fixed portion is ignored
                                 */
-       __le16 channel_list[1]; /* list of chanspecs */
+       union {
+               __le16 padding; /* Reserve space for at least 1 entry for abort
+                                * which uses an on stack brcmf_scan_params_le
+                                */
+               DECLARE_FLEX_ARRAY(__le16, channel_list);       /* chanspecs */
+       };
 };
 
 struct brcmf_scan_params_v2_le {
index 2b0f332043d7961c0a9e30d37fa7c8a0ffb7349d..1f3bde8ac73d46e5823afebdbff71b1ac8af4fad 100644 (file)
@@ -577,7 +577,7 @@ struct tx_msg {
     struct tib_structure tib;
     struct phy_header phy;
     struct mac_header mac;
-    UCHAR  var[1];
+    UCHAR  var[];
 };
 
 /****** ECF Receive Control Structure (RCS) Area at Shared RAM offset 0x0800  */
index 68e88224b8b1fc04ad78e5d87b0ab4328a05d9a7..ccedea7e8a50d68dc602baa8e563ff5b717cfd86 100644 (file)
@@ -128,12 +128,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
        case MT_EE_5GHZ:
                dev->mphy.cap.has_5ghz = true;
                break;
-       case MT_EE_2GHZ:
-               dev->mphy.cap.has_2ghz = true;
-               break;
        case MT_EE_DBDC:
                dev->dbdc_support = true;
                fallthrough;
+       case MT_EE_2GHZ:
+               dev->mphy.cap.has_2ghz = true;
+               break;
        default:
                dev->mphy.cap.has_2ghz = true;
                dev->mphy.cap.has_5ghz = true;
index b114babec698c00f30c5b3310186c4fa376ca10b..c93e6250cb8b4b5ffa0ff1ef59403718ed22eb78 100644 (file)
@@ -2524,7 +2524,7 @@ static int cmac_dma_init(struct rtw89_dev *rtwdev, u8 mac_idx)
        u32 reg;
        int ret;
 
-       if (chip_id != RTL8852A && chip_id != RTL8852B)
+       if (chip_id != RTL8852B)
                return 0;
 
        ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
index c8d20cddf65848d36788d44d5449480954e8f085..88f760a7cbc35469e20be2d09f9b2cfb92b8362a 100644 (file)
@@ -396,7 +396,7 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
        struct gnttab_map_grant_ref *gop = queue->tx_map_ops + *map_ops;
        struct xen_netif_tx_request *txp = first;
 
-       nr_slots = shinfo->nr_frags + 1;
+       nr_slots = shinfo->nr_frags + frag_overflow + 1;
 
        copy_count(skb) = 0;
        XENVIF_TX_CB(skb)->split_mask = 0;
@@ -462,8 +462,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
                }
        }
 
-       for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
-            shinfo->nr_frags++, gop++) {
+       for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS;
+            shinfo->nr_frags++, gop++, nr_slots--) {
                index = pending_index(queue->pending_cons++);
                pending_idx = queue->pending_ring[index];
                xenvif_tx_create_map_op(queue, pending_idx, txp,
@@ -476,12 +476,12 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
                        txp++;
        }
 
-       if (frag_overflow) {
+       if (nr_slots > 0) {
 
                shinfo = skb_shinfo(nskb);
                frags = shinfo->frags;
 
-               for (shinfo->nr_frags = 0; shinfo->nr_frags < frag_overflow;
+               for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
                     shinfo->nr_frags++, txp++, gop++) {
                        index = pending_index(queue->pending_cons++);
                        pending_idx = queue->pending_ring[index];
@@ -492,6 +492,11 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
                }
 
                skb_shinfo(skb)->frag_list = nskb;
+       } else if (nskb) {
+               /* A frag_list skb was allocated but it is no longer needed
+                * because enough slots were converted to copy ops above.
+                */
+               kfree_skb(nskb);
        }
 
        (*copy_ops) = cop - queue->tx_copy_ops;
index 37b6fa7466620436b2ab23cd00eb0de91309bb30..f3a01b79148cb1e3246d759cf0bdab809270eb2a 100644 (file)
@@ -3933,6 +3933,12 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
         */
        nvme_mpath_clear_ctrl_paths(ctrl);
 
+       /*
+        * Unquiesce io queues so any pending IO won't hang, especially
+        * those submitted from scan work
+        */
+       nvme_unquiesce_io_queues(ctrl);
+
        /* prevent racing with ns scanning */
        flush_work(&ctrl->scan_work);
 
@@ -3942,10 +3948,8 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
         * removing the namespaces' disks; fail all the queues now to avoid
         * potentially having to clean up the failed sync later.
         */
-       if (ctrl->state == NVME_CTRL_DEAD) {
+       if (ctrl->state == NVME_CTRL_DEAD)
                nvme_mark_namespaces_dead(ctrl);
-               nvme_unquiesce_io_queues(ctrl);
-       }
 
        /* this is a no-op when called from the controller reset handler */
        nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING_NOIO);
index 5c3250f36ce7764beccef76510a85c6999eb4daa..d39f3219358b9d761faa3e5437a4474924774adb 100644 (file)
@@ -786,11 +786,9 @@ int nvme_ns_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd,
        if (!(ioucmd->flags & IORING_URING_CMD_POLLED))
                return 0;
 
-       rcu_read_lock();
        req = READ_ONCE(ioucmd->cookie);
        if (req && blk_rq_is_poll(req))
                ret = blk_rq_poll(req, iob, poll_flags);
-       rcu_read_unlock();
        return ret;
 }
 #ifdef CONFIG_NVME_MULTIPATH
index baf69af7ea78efd27e57c1c2cfe763ff17867c4e..2f57da12d9836dd1af3beceb4d61e9e73ceb5930 100644 (file)
@@ -3402,7 +3402,8 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_DEVICE(0x1d97, 0x2263),   /* SPCC */
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE(0x144d, 0xa80b),   /* Samsung PM9B1 256G and 512G */
-               .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+               .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES |
+                               NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x144d, 0xa809),   /* Samsung MZALQ256HBJD 256G */
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE(0x144d, 0xa802),   /* Samsung SM953 */
index d433b2ec07a61fdb8ecafb65ad49ca62c67cd487..337a624a537ce14f764667e02a55607b54ca0e66 100644 (file)
@@ -883,6 +883,7 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new)
                goto out_cleanup_tagset;
 
        if (!new) {
+               nvme_start_freeze(&ctrl->ctrl);
                nvme_unquiesce_io_queues(&ctrl->ctrl);
                if (!nvme_wait_freeze_timeout(&ctrl->ctrl, NVME_IO_TIMEOUT)) {
                        /*
@@ -891,6 +892,7 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new)
                         * to be safe.
                         */
                        ret = -ENODEV;
+                       nvme_unfreeze(&ctrl->ctrl);
                        goto out_wait_freeze_timed_out;
                }
                blk_mq_update_nr_hw_queues(ctrl->ctrl.tagset,
@@ -940,7 +942,6 @@ static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl,
                bool remove)
 {
        if (ctrl->ctrl.queue_count > 1) {
-               nvme_start_freeze(&ctrl->ctrl);
                nvme_quiesce_io_queues(&ctrl->ctrl);
                nvme_sync_io_queues(&ctrl->ctrl);
                nvme_rdma_stop_io_queues(ctrl);
index 9ce417cd32a79b861d3e9ed044325c8ab87757a6..5b332d9f87fc3a20b803231879616eeb44a20260 100644 (file)
@@ -1868,6 +1868,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
                goto out_cleanup_connect_q;
 
        if (!new) {
+               nvme_start_freeze(ctrl);
                nvme_unquiesce_io_queues(ctrl);
                if (!nvme_wait_freeze_timeout(ctrl, NVME_IO_TIMEOUT)) {
                        /*
@@ -1876,6 +1877,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
                         * to be safe.
                         */
                        ret = -ENODEV;
+                       nvme_unfreeze(ctrl);
                        goto out_wait_freeze_timed_out;
                }
                blk_mq_update_nr_hw_queues(ctrl->tagset,
@@ -1980,7 +1982,6 @@ static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl,
        if (ctrl->queue_count <= 1)
                return;
        nvme_quiesce_admin_queue(ctrl);
-       nvme_start_freeze(ctrl);
        nvme_quiesce_io_queues(ctrl);
        nvme_sync_io_queues(ctrl);
        nvme_tcp_stop_io_queues(ctrl);
index e311d406b17053065b2f0699e92cda1c2e5db481..4999636eaa9267322b87846f65d2e775942d254d 100644 (file)
@@ -63,15 +63,14 @@ int of_reconfig_notifier_unregister(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
 
-#ifdef DEBUG
-const char *action_names[] = {
+static const char *action_names[] = {
+       [0] = "INVALID",
        [OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE",
        [OF_RECONFIG_DETACH_NODE] = "DETACH_NODE",
        [OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY",
        [OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY",
        [OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY",
 };
-#endif
 
 int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p)
 {
@@ -620,21 +619,9 @@ static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
                }
 
                ret = __of_add_property(ce->np, ce->prop);
-               if (ret) {
-                       pr_err("changeset: add_property failed @%pOF/%s\n",
-                               ce->np,
-                               ce->prop->name);
-                       break;
-               }
                break;
        case OF_RECONFIG_REMOVE_PROPERTY:
                ret = __of_remove_property(ce->np, ce->prop);
-               if (ret) {
-                       pr_err("changeset: remove_property failed @%pOF/%s\n",
-                               ce->np,
-                               ce->prop->name);
-                       break;
-               }
                break;
 
        case OF_RECONFIG_UPDATE_PROPERTY:
@@ -648,20 +635,17 @@ static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
                }
 
                ret = __of_update_property(ce->np, ce->prop, &old_prop);
-               if (ret) {
-                       pr_err("changeset: update_property failed @%pOF/%s\n",
-                               ce->np,
-                               ce->prop->name);
-                       break;
-               }
                break;
        default:
                ret = -EINVAL;
        }
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
-       if (ret)
+       if (ret) {
+               pr_err("changeset: apply failed: %-15s %pOF:%s\n",
+                      action_names[ce->action], ce->np, ce->prop->name);
                return ret;
+       }
 
        switch (ce->action) {
        case OF_RECONFIG_ATTACH_NODE:
@@ -947,6 +931,9 @@ int of_changeset_action(struct of_changeset *ocs, unsigned long action,
        if (!ce)
                return -ENOMEM;
 
+       if (WARN_ON(action >= ARRAY_SIZE(action_names)))
+               return -EINVAL;
+
        /* get a reference to the node */
        ce->action = action;
        ce->np = of_node_get(np);
index f26d2ba8a371538f31fc5bbc7a347db3646248e1..68278340cecfe5c8a20805c4ef85633b257c5d4b 100644 (file)
@@ -184,7 +184,8 @@ int __init ima_free_kexec_buffer(void)
        if (ret)
                return ret;
 
-       return memblock_phys_free(addr, size);
+       memblock_free_late(addr, size);
+       return 0;
 }
 #endif
 
index 0c3475e7d2ffbfddbb0e56a2e55094ea328d7a7e..6a557eb866d0a998bbf943a2ca17230ca8f0f2b2 100644 (file)
@@ -141,7 +141,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
        }
 
        /* setup generic device info */
-       device_set_node(&dev->dev, of_fwnode_handle(np));
+       device_set_node(&dev->dev, of_fwnode_handle(of_node_get(np)));
        dev->dev.parent = parent ? : &platform_bus;
 
        if (bus_id)
@@ -239,7 +239,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
        dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
 
        /* setup generic device info */
-       device_set_node(&dev->dev, of_fwnode_handle(node));
+       device_set_node(&dev->dev, of_fwnode_handle(of_node_get(node)));
        dev->dev.parent = parent ? : &platform_bus;
        dev->dev.platform_data = platform_data;
        if (bus_id)
index a406a12eb20804d658cb0adab9841fba31f7c5ff..b545fcb22536d1f51c93687e6f8c2fa9f9c11278 100644 (file)
@@ -664,12 +664,12 @@ static void __init of_unittest_parse_phandle_with_args_map(void)
        memset(&args, 0, sizeof(args));
 
        EXPECT_BEGIN(KERN_INFO,
-                    "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle");
+                    "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle 12345678");
 
        rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-phandle",
                                            "phandle", 0, &args);
        EXPECT_END(KERN_INFO,
-                  "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle");
+                  "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle 12345678");
 
        unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
 
index bf3405f4289e8f82ba9dd72d580a0c57902e70a3..8b1dcd537020f5c78937660ba44715945a7d050c 100644 (file)
@@ -121,6 +121,8 @@ module_param(sba_reserve_agpgart, int, 0444);
 MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART");
 #endif
 
+struct proc_dir_entry *proc_runway_root __ro_after_init;
+struct proc_dir_entry *proc_mckinley_root __ro_after_init;
 
 /************************************
 ** SBA register read and write support
@@ -1968,11 +1970,15 @@ static int __init sba_driver_callback(struct parisc_device *dev)
 #ifdef CONFIG_PROC_FS
        switch (dev->id.hversion) {
        case PLUTO_MCKINLEY_PORT:
+               if (!proc_mckinley_root)
+                       proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
                root = proc_mckinley_root;
                break;
        case ASTRO_RUNWAY_PORT:
        case IKE_MERCED_PORT:
        default:
+               if (!proc_runway_root)
+                       proc_runway_root = proc_mkdir("bus/runway", NULL);
                root = proc_runway_root;
                break;
        }
index 0dcc497b0449a0487bf76857110dfebe77de33a6..5e4475254bd0a374cec4294c62222d673014766d 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/sysctl.h>
 
 #include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/uaccess.h>
 #include <asm/superio.h>
 
@@ -226,9 +225,9 @@ static int parport_PS2_supported(struct parport *pb)
 
 /* --- Initialisation code -------------------------------- */
 
-struct parport *parport_gsc_probe_port(unsigned long base,
+static struct parport *parport_gsc_probe_port(unsigned long base,
                                       unsigned long base_hi, int irq,
-                                      int dma, struct parisc_device *padev)
+                                      struct parisc_device *padev)
 {
        struct parport_gsc_private *priv;
        struct parport_operations *ops;
@@ -250,12 +249,9 @@ struct parport *parport_gsc_probe_port(unsigned long base,
        }
        priv->ctr = 0xc;
        priv->ctr_writable = 0xff;
-       priv->dma_buf = NULL;
-       priv->dma_handle = 0;
        p->base = base;
        p->base_hi = base_hi;
        p->irq = irq;
-       p->dma = dma;
        p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
        p->ops = ops;
        p->private_data = priv;
@@ -286,17 +282,9 @@ struct parport *parport_gsc_probe_port(unsigned long base,
        if (p->irq == PARPORT_IRQ_AUTO) {
                p->irq = PARPORT_IRQ_NONE;
        }
-       if (p->irq != PARPORT_IRQ_NONE) {
+       if (p->irq != PARPORT_IRQ_NONE)
                pr_cont(", irq %d", p->irq);
 
-               if (p->dma == PARPORT_DMA_AUTO) {
-                       p->dma = PARPORT_DMA_NONE;
-               }
-       }
-       if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq
-                                           is mandatory (see above) */
-               p->dma = PARPORT_DMA_NONE;
-
        pr_cont(" [");
 #define printmode(x)                                                   \
 do {                                                                   \
@@ -321,7 +309,6 @@ do {                                                                        \
                        pr_warn("%s: irq %d in use, resorting to polled operation\n",
                                p->name, p->irq);
                        p->irq = PARPORT_IRQ_NONE;
-                       p->dma = PARPORT_DMA_NONE;
                }
        }
 
@@ -369,8 +356,7 @@ static int __init parport_init_chip(struct parisc_device *dev)
                pr_info("%s: enhanced parport-modes not supported\n", __func__);
        }
        
-       p = parport_gsc_probe_port(port, 0, dev->irq,
-                       /* PARPORT_IRQ_NONE */ PARPORT_DMA_NONE, dev);
+       p = parport_gsc_probe_port(port, 0, dev->irq, dev);
        if (p)
                parport_count++;
        dev_set_drvdata(&dev->dev, p);
@@ -382,16 +368,10 @@ static void __exit parport_remove_chip(struct parisc_device *dev)
 {
        struct parport *p = dev_get_drvdata(&dev->dev);
        if (p) {
-               struct parport_gsc_private *priv = p->private_data;
                struct parport_operations *ops = p->ops;
                parport_remove_port(p);
-               if (p->dma != PARPORT_DMA_NONE)
-                       free_dma(p->dma);
                if (p->irq != PARPORT_IRQ_NONE)
                        free_irq(p->irq, p);
-               if (priv->dma_buf)
-                       dma_free_coherent(&priv->dev->dev, PAGE_SIZE,
-                                         priv->dma_buf, priv->dma_handle);
                kfree (p->private_data);
                parport_put_port(p);
                kfree (ops); /* hope no-one cached it */
index 9301217edf12cc3eeff572a70ea4460190a62325..d447a568c2570be63798c4e641356d4be6df4b2a 100644 (file)
@@ -63,8 +63,6 @@ struct parport_gsc_private {
        int writeIntrThreshold;
 
        /* buffer suitable for DMA, if DMA enabled */
-       char *dma_buf;
-       dma_addr_t dma_handle;
        struct pci_dev *dev;
 };
 
@@ -199,9 +197,4 @@ extern void parport_gsc_inc_use_count(void);
 
 extern void parport_gsc_dec_use_count(void);
 
-extern struct parport *parport_gsc_probe_port(unsigned long base,
-                                               unsigned long base_hi,
-                                               int irq, int dma,
-                                               struct parisc_device *padev);
-
 #endif /* __DRIVERS_PARPORT_PARPORT_GSC_H */
index 5bc81cc0a2de4d392052bb068b10075a9ceb0055..46b252bbe5000140fa2075e42f750f15e7c4d9c6 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
+#include <linux/of.h>
 #include <linux/proc_fs.h>
 #include <linux/slab.h>
 
@@ -332,6 +333,7 @@ void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
  */
 void pci_bus_add_device(struct pci_dev *dev)
 {
+       struct device_node *dn = dev->dev.of_node;
        int retval;
 
        /*
@@ -344,7 +346,7 @@ void pci_bus_add_device(struct pci_dev *dev)
        pci_proc_attach_device(dev);
        pci_bridge_d3_update(dev);
 
-       dev->match_driver = true;
+       dev->match_driver = !dn || of_device_is_available(dn);
        retval = device_attach(&dev->dev);
        if (retval < 0 && retval != -EPROBE_DEFER)
                pci_warn(dev, "device attach failed (%d)\n", retval);
index 8d49bad7f84728add52a9f3b53d6f189de69813b..0859be86e71834358b80fed62e12339c1cd1cd42 100644 (file)
@@ -179,7 +179,6 @@ config PCI_MVEBU
        depends on MVEBU_MBUS
        depends on ARM
        depends on OF
-       depends on BROKEN
        select PCI_BRIDGE_EMUL
        help
         Add support for Marvell EBU PCIe controller. This PCIe controller
index cf61733bf78d24a99114bb8bdf3262a771d5b44b..9952057c8819c86ac7bb97dfe709f6337ddfa7c6 100644 (file)
@@ -485,20 +485,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
        if (ret)
                goto err_remove_edma;
 
-       if (dw_pcie_link_up(pci)) {
-               dw_pcie_print_link_status(pci);
-       } else {
+       if (!dw_pcie_link_up(pci)) {
                ret = dw_pcie_start_link(pci);
                if (ret)
                        goto err_remove_edma;
-
-               if (pci->ops && pci->ops->start_link) {
-                       ret = dw_pcie_wait_for_link(pci);
-                       if (ret)
-                               goto err_stop_link;
-               }
        }
 
+       /* Ignore errors, the link may come up later */
+       dw_pcie_wait_for_link(pci);
+
        bridge->sysdata = pp;
 
        ret = pci_host_probe(bridge);
index c87848cd8686c0337bbd2db21f9c7b6d66bf9001..1f2ee71da4da2ad87655eaac3172186ae4c58124 100644 (file)
@@ -644,20 +644,9 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index)
        dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0);
 }
 
-void dw_pcie_print_link_status(struct dw_pcie *pci)
-{
-       u32 offset, val;
-
-       offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
-       val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
-
-       dev_info(pci->dev, "PCIe Gen.%u x%u link up\n",
-                FIELD_GET(PCI_EXP_LNKSTA_CLS, val),
-                FIELD_GET(PCI_EXP_LNKSTA_NLW, val));
-}
-
 int dw_pcie_wait_for_link(struct dw_pcie *pci)
 {
+       u32 offset, val;
        int retries;
 
        /* Check if the link is up or not */
@@ -673,7 +662,12 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci)
                return -ETIMEDOUT;
        }
 
-       dw_pcie_print_link_status(pci);
+       offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+       val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
+
+       dev_info(pci->dev, "PCIe Gen.%u x%u link up\n",
+                FIELD_GET(PCI_EXP_LNKSTA_CLS, val),
+                FIELD_GET(PCI_EXP_LNKSTA_NLW, val));
 
        return 0;
 }
index 615660640801968cf5b76d36b9ceab3c3984d3f1..79713ce075cc1b6b3c1eff6b8535813c87837076 100644 (file)
@@ -429,7 +429,6 @@ void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);
 int dw_pcie_edma_detect(struct dw_pcie *pci);
 void dw_pcie_edma_remove(struct dw_pcie *pci);
-void dw_pcie_print_link_status(struct dw_pcie *pci);
 
 static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
 {
index 328d1e416014762dcebd78f4187b3e9a1b34cb9e..601129772b2d5021afde6eeddc479506852f4902 100644 (file)
@@ -498,6 +498,7 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge)
                                acpiphp_native_scan_bridge(dev);
                }
        } else {
+               LIST_HEAD(add_list);
                int max, pass;
 
                acpiphp_rescan_slot(slot);
@@ -511,10 +512,15 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge)
                                if (pass && dev->subordinate) {
                                        check_hotplug_bridge(slot, dev);
                                        pcibios_resource_survey_bus(dev->subordinate);
+                                       if (pci_is_root_bus(bus))
+                                               __pci_bus_size_bridges(dev->subordinate, &add_list);
                                }
                        }
                }
-               pci_assign_unassigned_bridge_resources(bus->self);
+               if (pci_is_root_bus(bus))
+                       __pci_bus_assign_resources(bus, &add_list, NULL);
+               else
+                       pci_assign_unassigned_bridge_resources(bus->self);
        }
 
        acpiphp_sanitize_bus(bus);
index e51219f9f523cd557670e51f7f0929927431ef15..3c158b17dcb53730ae0a9179f4985245ad457463 100644 (file)
@@ -34,11 +34,6 @@ int pci_set_of_node(struct pci_dev *dev)
        if (!node)
                return 0;
 
-       if (!of_device_is_available(node)) {
-               of_node_put(node);
-               return -ENODEV;
-       }
-
        device_set_node(&dev->dev, of_fwnode_handle(node));
        return 0;
 }
index 2585ef2b2793505342905ff44cebc2f07a9d28fb..115b83e2d8e65a037f5b7f86fec6a243c03eebf4 100644 (file)
@@ -1038,6 +1038,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
        const struct msm_pingroup *g;
+       u32 intr_target_mask = GENMASK(2, 0);
        unsigned long flags;
        bool was_enabled;
        u32 val;
@@ -1074,13 +1075,15 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
         * With intr_target_use_scm interrupts are routed to
         * application cpu using scm calls.
         */
+       if (g->intr_target_width)
+               intr_target_mask = GENMASK(g->intr_target_width - 1, 0);
+
        if (pctrl->intr_target_use_scm) {
                u32 addr = pctrl->phys_base[0] + g->intr_target_reg;
                int ret;
 
                qcom_scm_io_readl(addr, &val);
-
-               val &= ~(7 << g->intr_target_bit);
+               val &= ~(intr_target_mask << g->intr_target_bit);
                val |= g->intr_target_kpss_val << g->intr_target_bit;
 
                ret = qcom_scm_io_writel(addr, val);
@@ -1090,7 +1093,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
                                d->hwirq);
        } else {
                val = msm_readl_intr_target(pctrl, g);
-               val &= ~(7 << g->intr_target_bit);
+               val &= ~(intr_target_mask << g->intr_target_bit);
                val |= g->intr_target_kpss_val << g->intr_target_bit;
                msm_writel_intr_target(val, pctrl, g);
        }
index 5e4410bed8237dc029c3ac9986a9a5ceb12a0d4b..1d2f2e904da19053d9f303e825a3c2479c54ae75 100644 (file)
@@ -59,6 +59,7 @@ struct pinctrl_pin_desc;
  * @intr_status_bit:      Offset in @intr_status_reg for reading and acking the interrupt
  *                        status.
  * @intr_target_bit:      Offset in @intr_target_reg for configuring the interrupt routing.
+ * @intr_target_width:    Number of bits used for specifying interrupt routing target.
  * @intr_target_kpss_val: Value in @intr_target_bit for specifying that the interrupt from
  *                        this gpio should get routed to the KPSS processor.
  * @intr_raw_status_bit:  Offset in @intr_cfg_reg for the raw status bit.
@@ -100,6 +101,7 @@ struct msm_pingroup {
        unsigned intr_ack_high:1;
 
        unsigned intr_target_bit:5;
+       unsigned intr_target_width:5;
        unsigned intr_target_kpss_val:5;
        unsigned intr_raw_status_bit:5;
        unsigned intr_polarity_bit:5;
index 8a5cd15512b971bc1d08c344fb0d5110906c46fc..8fdea25d8d67e1ef36868c552ba51da093e9d662 100644 (file)
@@ -46,6 +46,7 @@
                .intr_enable_bit = 0,           \
                .intr_status_bit = 0,           \
                .intr_target_bit = 5,           \
+               .intr_target_width = 4,         \
                .intr_target_kpss_val = 3,      \
                .intr_raw_status_bit = 4,       \
                .intr_polarity_bit = 1,         \
index a79318e90a13917ab090c363de3cb6c038a57bb0..b600b77d91ef2c3834d6e837b1f64f78f962ba97 100644 (file)
@@ -887,6 +887,7 @@ static bool mlxbf_tmfifo_virtio_notify(struct virtqueue *vq)
                        tm_vdev = fifo->vdev[VIRTIO_ID_CONSOLE];
                        mlxbf_tmfifo_console_output(tm_vdev, vring);
                        spin_unlock_irqrestore(&fifo->spin_lock[0], flags);
+                       set_bit(MLXBF_TM_TX_LWM_IRQ, &fifo->pend_events);
                } else if (test_and_set_bit(MLXBF_TM_TX_LWM_IRQ,
                                            &fifo->pend_events)) {
                        return true;
index ab69d517a36ae7fb64e3e3f711051546cde63b9f..a70e67749be33476be9a3ba178cd88a55b87410f 100644 (file)
@@ -176,7 +176,8 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
 
 int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
 {
-       u8 mode, flag = 0;
+       u8 flag = 0;
+       int mode;
        int src;
 
        mode = amd_pmf_get_pprof_modes(dev);
index d2fee9a3e2390a23f38e5d6dfa3388ef56cb0797..6d9297c1d96c102fceac90f71c6cfa19002cbdc9 100644 (file)
@@ -1049,6 +1049,11 @@ static const struct key_entry ideapad_keymap[] = {
        { KE_IGNORE,    0x03 | IDEAPAD_WMI_KEY },
        /* Customizable Lenovo Hotkey ("star" with 'S' inside) */
        { KE_KEY,       0x01 | IDEAPAD_WMI_KEY, { KEY_FAVORITES } },
+       { KE_KEY,       0x04 | IDEAPAD_WMI_KEY, { KEY_SELECTIVE_SCREENSHOT } },
+       /* Lenovo Support */
+       { KE_KEY,       0x07 | IDEAPAD_WMI_KEY, { KEY_HELP } },
+       { KE_KEY,       0x0e | IDEAPAD_WMI_KEY, { KEY_PICKUP_PHONE } },
+       { KE_KEY,       0x0f | IDEAPAD_WMI_KEY, { KEY_HANGUP_PHONE } },
        /* Dark mode toggle */
        { KE_KEY,       0x13 | IDEAPAD_WMI_KEY, { KEY_PROG1 } },
        /* Sound profile switch */
index 1f59ac55c5f7290ab0bc39bbbf237a8ced6a179d..a95004e3d80b23a735bc4dbb9eaab449b2aff120 100644 (file)
@@ -335,8 +335,8 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
 
                node = dev_to_node(&_pci_dev->dev);
                if (node == NUMA_NO_NODE) {
-                       pr_info("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n",
-                               cpu, bus_no, dev, fn);
+                       pr_info_once("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n",
+                                    cpu, bus_no, dev, fn);
                        continue;
                }
 
index 41676188b373891f4888e44b3d5274a1ec82b405..e1fbc35504d4985e0949d051ce1231584a544c42 100644 (file)
@@ -24,6 +24,10 @@ static bool ec_trigger __read_mostly;
 module_param(ec_trigger, bool, 0444);
 MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events");
 
+static bool force;
+module_param(force, bool, 0444);
+MODULE_PARM_DESC(force, "Force loading on boards without a convertible DMI chassis-type");
+
 static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
        {
                /* Lenovo Yoga 7 14ARB7 */
@@ -32,6 +36,27 @@ static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
                },
        },
+       {
+               /* Lenovo Yoga 7 14ACN6 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "82N7"),
+               },
+       },
+       { }
+};
+
+static const struct dmi_system_id allowed_chasis_types_dmi_table[] = {
+       {
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31" /* Convertible */),
+               },
+       },
+       {
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32" /* Detachable */),
+               },
+       },
        { }
 };
 
@@ -111,6 +136,13 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
        struct input_dev *input_dev;
        int err;
 
+       if (!dmi_check_system(allowed_chasis_types_dmi_table)) {
+               if (force)
+                       dev_info(&wdev->dev, "Force loading Lenovo YMC support\n");
+               else
+                       return -ENODEV;
+       }
+
        ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table);
 
        priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
index 67367f010139e21fbde7b3a345c80c36ab1bc31a..7d33977d9c6099401b4d7d0fc8dc4136de7da81e 100644 (file)
 #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET        0x37
 #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET       0x3a
 #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET  0x3b
-#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET       0x3c
-#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET       0x3d
-#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET       0x3e
-#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET       0x3f
 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET     0x40
 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET        0x41
 #define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET     0x42
 #define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET        0xaa
 #define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab
 #define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON         0xb2
+#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET       0xb6
+#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET       0xb7
+#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET       0xb8
+#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET       0xb9
 #define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET     0xc2
 #define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT   0xc3
 #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET   0xc7
                                         MLXPLAT_CPLD_AGGR_MASK_LC_SDWN)
 #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1
 #define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2       BIT(2)
-#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT     BIT(4)
+#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT     GENMASK(5, 4)
 #define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6)
 #define MLXPLAT_CPLD_PSU_MASK          GENMASK(1, 0)
 #define MLXPLAT_CPLD_PWR_MASK          GENMASK(1, 0)
 #define MLXPLAT_CPLD_GWP_MASK          GENMASK(0, 0)
 #define MLXPLAT_CPLD_EROT_MASK         GENMASK(1, 0)
 #define MLXPLAT_CPLD_PWR_BUTTON_MASK   BIT(0)
-#define MLXPLAT_CPLD_LATCH_RST_MASK    BIT(5)
+#define MLXPLAT_CPLD_LATCH_RST_MASK    BIT(6)
 #define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3)
 #define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4)
 #define MLXPLAT_CPLD_INTRUSION_MASK    BIT(6)
@@ -2356,7 +2356,7 @@ mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_k
                                             u8 action)
 {
        dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button");
-       kernel_halt();
+       kernel_power_off();
        return 0;
 }
 
@@ -2475,7 +2475,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = {
                .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET,
                .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK,
                .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data),
-               .inversed = 0,
+               .inversed = 1,
                .health = false,
        },
        {
@@ -2484,7 +2484,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = {
                .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET,
                .mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK,
                .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data),
-               .inversed = 0,
+               .inversed = 1,
                .health = false,
                .ind = 8,
        },
@@ -3677,7 +3677,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
        {
                .label = "latch_reset",
                .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
-               .mask = GENMASK(7, 0) & ~BIT(5),
+               .mask = GENMASK(7, 0) & ~BIT(6),
                .mode = 0200,
        },
        {
@@ -6238,8 +6238,6 @@ static void mlxplat_i2c_mux_topolgy_exit(struct mlxplat_priv *priv)
                if (priv->pdev_mux[i])
                        platform_device_unregister(priv->pdev_mux[i]);
        }
-
-       mlxplat_post_exit();
 }
 
 static int mlxplat_i2c_main_complition_notify(void *handle, int id)
@@ -6369,6 +6367,7 @@ static void __exit mlxplat_exit(void)
                pm_power_off = NULL;
        mlxplat_pre_exit(priv);
        mlxplat_i2c_main_exit(priv);
+       mlxplat_post_exit();
 }
 module_exit(mlxplat_exit);
 
index ff93986e3d35ae9533637c43ccbf3b1e3e3bf13e..f26a3121092f9790ea78567d4db97ae17211cbf2 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/string.h>
 
-static const char *const SM_ECO_NAME       = "eco";
-static const char *const SM_COMFORT_NAME   = "comfort";
-static const char *const SM_SPORT_NAME     = "sport";
-static const char *const SM_TURBO_NAME     = "turbo";
-
-static const char *const FM_AUTO_NAME     = "auto";
-static const char *const FM_SILENT_NAME   = "silent";
-static const char *const FM_BASIC_NAME    = "basic";
-static const char *const FM_ADVANCED_NAME = "advanced";
+#define SM_ECO_NAME            "eco"
+#define SM_COMFORT_NAME                "comfort"
+#define SM_SPORT_NAME          "sport"
+#define SM_TURBO_NAME          "turbo"
+
+#define FM_AUTO_NAME           "auto"
+#define FM_SILENT_NAME         "silent"
+#define FM_BASIC_NAME          "basic"
+#define FM_ADVANCED_NAME       "advanced"
 
 static const char * const ALLOWED_FW_0[] __initconst = {
        "14C1EMS1.012",
index 2c2abf69f049f2e5a2914cbbf891076e61e4dbd8..8158e3cf5d6dec12903c1b8b97f682da451f5df3 100644 (file)
@@ -329,6 +329,19 @@ static const struct smi_node cs35l41_hda = {
        .bus_type = SMI_AUTO_DETECT,
 };
 
+static const struct smi_node cs35l56_hda = {
+       .instances = {
+               { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
+               { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
+               { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
+               { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
+               /* a 5th entry is an alias address, not a real device */
+               { "cs35l56-hda_dummy_dev" },
+               {}
+       },
+       .bus_type = SMI_AUTO_DETECT,
+};
+
 /*
  * Note new device-ids must also be added to ignore_serial_bus_ids in
  * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
@@ -337,6 +350,7 @@ static const struct acpi_device_id smi_acpi_ids[] = {
        { "BSG1160", (unsigned long)&bsg1160_data },
        { "BSG2150", (unsigned long)&bsg2150_data },
        { "CSC3551", (unsigned long)&cs35l41_hda },
+       { "CSC3556", (unsigned long)&cs35l56_hda },
        { "INT3515", (unsigned long)&int3515_data },
        /* Non-conforming _HID for Cirrus Logic already released */
        { "CLSA0100", (unsigned long)&cs35l41_hda },
index 4e646e5e48f6800535817b0ba34499d148fa1ebf..8fac57b28f8a3cdb89ef2e024bbaaa52c8eca1f3 100644 (file)
@@ -818,7 +818,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
                return -EINVAL;
 
        ra.reg = rd->regs[rpi->id];
-       if (!ra.reg)
+       if (!ra.reg.val)
                return -EINVAL;
 
        /* non-hardware data are collected by the polling thread */
@@ -830,7 +830,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
        ra.mask = rpi->mask;
 
        if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
-               pr_debug("failed to read reg 0x%llx for %s:%s\n", ra.reg, rd->rp->name, rd->name);
+               pr_debug("failed to read reg 0x%llx for %s:%s\n", ra.reg.val, rd->rp->name, rd->name);
                return -EIO;
        }
 
@@ -920,7 +920,7 @@ static int rapl_check_unit_core(struct rapl_domain *rd)
        ra.mask = ~0;
        if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
                pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
-                       ra.reg, rd->rp->name, rd->name);
+                       ra.reg.val, rd->rp->name, rd->name);
                return -ENODEV;
        }
 
@@ -948,7 +948,7 @@ static int rapl_check_unit_atom(struct rapl_domain *rd)
        ra.mask = ~0;
        if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
                pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
-                       ra.reg, rd->rp->name, rd->name);
+                       ra.reg.val, rd->rp->name, rd->name);
                return -ENODEV;
        }
 
@@ -1135,7 +1135,7 @@ static int rapl_check_unit_tpmi(struct rapl_domain *rd)
        ra.mask = ~0;
        if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
                pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
-                       ra.reg, rd->rp->name, rd->name);
+                       ra.reg.val, rd->rp->name, rd->name);
                return -ENODEV;
        }
 
@@ -1411,8 +1411,8 @@ static int rapl_get_domain_unit(struct rapl_domain *rd)
        struct rapl_defaults *defaults = get_defaults(rd->rp);
        int ret;
 
-       if (!rd->regs[RAPL_DOMAIN_REG_UNIT]) {
-               if (!rd->rp->priv->reg_unit) {
+       if (!rd->regs[RAPL_DOMAIN_REG_UNIT].val) {
+               if (!rd->rp->priv->reg_unit.val) {
                        pr_err("No valid Unit register found\n");
                        return -ENODEV;
                }
index 569e25eab1e1b6e4da8cde85fb1a2f774e663214..dd471021f23716e9c5883612da1ef9f9dc9f8cda 100644 (file)
@@ -34,28 +34,32 @@ static struct rapl_if_priv *rapl_msr_priv;
 
 static struct rapl_if_priv rapl_msr_priv_intel = {
        .type = RAPL_IF_MSR,
-       .reg_unit = MSR_RAPL_POWER_UNIT,
-       .regs[RAPL_DOMAIN_PACKAGE] = {
-               MSR_PKG_POWER_LIMIT, MSR_PKG_ENERGY_STATUS, MSR_PKG_PERF_STATUS, 0, MSR_PKG_POWER_INFO },
-       .regs[RAPL_DOMAIN_PP0] = {
-               MSR_PP0_POWER_LIMIT, MSR_PP0_ENERGY_STATUS, 0, MSR_PP0_POLICY, 0 },
-       .regs[RAPL_DOMAIN_PP1] = {
-               MSR_PP1_POWER_LIMIT, MSR_PP1_ENERGY_STATUS, 0, MSR_PP1_POLICY, 0 },
-       .regs[RAPL_DOMAIN_DRAM] = {
-               MSR_DRAM_POWER_LIMIT, MSR_DRAM_ENERGY_STATUS, MSR_DRAM_PERF_STATUS, 0, MSR_DRAM_POWER_INFO },
-       .regs[RAPL_DOMAIN_PLATFORM] = {
-               MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0},
+       .reg_unit.msr = MSR_RAPL_POWER_UNIT,
+       .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_LIMIT].msr   = MSR_PKG_POWER_LIMIT,
+       .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr  = MSR_PKG_ENERGY_STATUS,
+       .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PERF].msr    = MSR_PKG_PERF_STATUS,
+       .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_INFO].msr    = MSR_PKG_POWER_INFO,
+       .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_LIMIT].msr       = MSR_PP0_POWER_LIMIT,
+       .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr      = MSR_PP0_ENERGY_STATUS,
+       .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_POLICY].msr      = MSR_PP0_POLICY,
+       .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_LIMIT].msr       = MSR_PP1_POWER_LIMIT,
+       .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_STATUS].msr      = MSR_PP1_ENERGY_STATUS,
+       .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_POLICY].msr      = MSR_PP1_POLICY,
+       .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_LIMIT].msr      = MSR_DRAM_POWER_LIMIT,
+       .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_STATUS].msr     = MSR_DRAM_ENERGY_STATUS,
+       .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_PERF].msr       = MSR_DRAM_PERF_STATUS,
+       .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_INFO].msr       = MSR_DRAM_POWER_INFO,
+       .regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_LIMIT].msr  = MSR_PLATFORM_POWER_LIMIT,
+       .regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_STATUS].msr = MSR_PLATFORM_ENERGY_STATUS,
        .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2),
        .limits[RAPL_DOMAIN_PLATFORM] = BIT(POWER_LIMIT2),
 };
 
 static struct rapl_if_priv rapl_msr_priv_amd = {
        .type = RAPL_IF_MSR,
-       .reg_unit = MSR_AMD_RAPL_POWER_UNIT,
-       .regs[RAPL_DOMAIN_PACKAGE] = {
-               0, MSR_AMD_PKG_ENERGY_STATUS, 0, 0, 0 },
-       .regs[RAPL_DOMAIN_PP0] = {
-               0, MSR_AMD_CORE_ENERGY_STATUS, 0, 0, 0 },
+       .reg_unit.msr = MSR_AMD_RAPL_POWER_UNIT,
+       .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr  = MSR_AMD_PKG_ENERGY_STATUS,
+       .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr      = MSR_AMD_CORE_ENERGY_STATUS,
 };
 
 /* Handles CPU hotplug on multi-socket systems.
@@ -99,10 +103,8 @@ static int rapl_cpu_down_prep(unsigned int cpu)
 
 static int rapl_msr_read_raw(int cpu, struct reg_action *ra)
 {
-       u32 msr = (u32)ra->reg;
-
-       if (rdmsrl_safe_on_cpu(cpu, msr, &ra->value)) {
-               pr_debug("failed to read msr 0x%x on cpu %d\n", msr, cpu);
+       if (rdmsrl_safe_on_cpu(cpu, ra->reg.msr, &ra->value)) {
+               pr_debug("failed to read msr 0x%x on cpu %d\n", ra->reg.msr, cpu);
                return -EIO;
        }
        ra->value &= ra->mask;
@@ -112,17 +114,16 @@ static int rapl_msr_read_raw(int cpu, struct reg_action *ra)
 static void rapl_msr_update_func(void *info)
 {
        struct reg_action *ra = info;
-       u32 msr = (u32)ra->reg;
        u64 val;
 
-       ra->err = rdmsrl_safe(msr, &val);
+       ra->err = rdmsrl_safe(ra->reg.msr, &val);
        if (ra->err)
                return;
 
        val &= ~ra->mask;
        val |= ra->value;
 
-       ra->err = wrmsrl_safe(msr, val);
+       ra->err = wrmsrl_safe(ra->reg.msr, val);
 }
 
 static int rapl_msr_write_raw(int cpu, struct reg_action *ra)
@@ -171,7 +172,7 @@ static int rapl_msr_probe(struct platform_device *pdev)
 
        if (id) {
                rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] |= BIT(POWER_LIMIT4);
-               rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] =
+               rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4].msr =
                        MSR_VR_CURRENT_CONFIG;
                pr_info("PL4 support detected.\n");
        }
index 4f4f13ded225c4f33f1933f1598cf0ca5914840a..891c90fefd8b72157cb978b7ee36201d8c1e72a5 100644 (file)
@@ -59,10 +59,10 @@ static struct powercap_control_type *tpmi_control_type;
 
 static int tpmi_rapl_read_raw(int id, struct reg_action *ra)
 {
-       if (!ra->reg)
+       if (!ra->reg.mmio)
                return -EINVAL;
 
-       ra->value = readq((void __iomem *)ra->reg);
+       ra->value = readq(ra->reg.mmio);
 
        ra->value &= ra->mask;
        return 0;
@@ -72,15 +72,15 @@ static int tpmi_rapl_write_raw(int id, struct reg_action *ra)
 {
        u64 val;
 
-       if (!ra->reg)
+       if (!ra->reg.mmio)
                return -EINVAL;
 
-       val = readq((void __iomem *)ra->reg);
+       val = readq(ra->reg.mmio);
 
        val &= ~ra->mask;
        val |= ra->value;
 
-       writeq(val, (void __iomem *)ra->reg);
+       writeq(val, ra->reg.mmio);
        return 0;
 }
 
@@ -138,8 +138,7 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset)
        enum tpmi_rapl_register reg_index;
        enum rapl_domain_reg_id reg_id;
        int tpmi_domain_size, tpmi_domain_flags;
-       u64 *tpmi_rapl_regs = trp->base + offset;
-       u64 tpmi_domain_header = readq((void __iomem *)tpmi_rapl_regs);
+       u64 tpmi_domain_header = readq(trp->base + offset);
 
        /* Domain Parent bits are ignored for now */
        tpmi_domain_version = tpmi_domain_header & 0xff;
@@ -180,7 +179,7 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset)
                return -EINVAL;
        }
 
-       if (trp->priv.regs[domain_type][RAPL_DOMAIN_REG_UNIT]) {
+       if (trp->priv.regs[domain_type][RAPL_DOMAIN_REG_UNIT].mmio) {
                pr_warn(FW_BUG "Duplicate Domain type %d\n", tpmi_domain_type);
                return -EINVAL;
        }
@@ -218,7 +217,7 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset)
                default:
                        continue;
                }
-               trp->priv.regs[domain_type][reg_id] = (u64)&tpmi_rapl_regs[reg_index];
+               trp->priv.regs[domain_type][reg_id].mmio = trp->base + offset + reg_index * 8;
        }
 
        return 0;
index dfd5ec9f75c90fd69cd2c78aaa31e04284d9acf6..a0621665a6d22dfe39e5f37eef25e525e23f6ecc 100644 (file)
@@ -778,9 +778,6 @@ static int da9063_check_xvp_constraints(struct regulator_config *config)
        const struct notification_limit *uv_l = &constr->under_voltage_limits;
        const struct notification_limit *ov_l = &constr->over_voltage_limits;
 
-       if (!config->init_data) /* No config in DT, pointers will be invalid */
-               return 0;
-
        /* make sure that only one severity is used to clarify if unchanged, enabled or disabled */
        if ((!!uv_l->prot + !!uv_l->err + !!uv_l->warn) > 1) {
                dev_err(config->dev, "%s: at most one voltage monitoring severity allowed!\n",
@@ -1031,9 +1028,12 @@ static int da9063_regulator_probe(struct platform_device *pdev)
                        config.of_node = da9063_reg_matches[id].of_node;
                config.regmap = da9063->regmap;
 
-               ret = da9063_check_xvp_constraints(&config);
-               if (ret)
-                       return ret;
+               /* Checking constraints requires init_data from DT. */
+               if (config.init_data) {
+                       ret = da9063_check_xvp_constraints(&config);
+                       if (ret)
+                               return ret;
+               }
 
                regl->rdev = devm_regulator_register(&pdev->dev, &regl->desc,
                                                     &config);
index f3b280af0773786999b36877f00f1eb52cf88d21..cd077b7c4aff373e6f1f8ba7095d0b502e5db596 100644 (file)
@@ -1068,7 +1068,7 @@ static const struct rpmh_vreg_init_data pm8550_vreg_data[] = {
        RPMH_VREG("ldo9",   "ldo%s9",  &pmic5_pldo,    "vdd-l8-l9"),
        RPMH_VREG("ldo10",  "ldo%s10", &pmic5_nldo515,    "vdd-l1-l4-l10"),
        RPMH_VREG("ldo11",  "ldo%s11", &pmic5_nldo515,    "vdd-l11"),
-       RPMH_VREG("ldo12",  "ldo%s12", &pmic5_pldo,    "vdd-l12"),
+       RPMH_VREG("ldo12",  "ldo%s12", &pmic5_nldo515,    "vdd-l12"),
        RPMH_VREG("ldo13",  "ldo%s13", &pmic5_pldo,    "vdd-l2-l13-l14"),
        RPMH_VREG("ldo14",  "ldo%s14", &pmic5_pldo,    "vdd-l2-l13-l14"),
        RPMH_VREG("ldo15",  "ldo%s15", &pmic5_nldo515,    "vdd-l15"),
index 1d195429753dd590ac90d82217d9994f0bc49607..613eab729704648c5daeb430355bba22157d0dee 100644 (file)
@@ -716,7 +716,6 @@ struct qeth_card_info {
        u16 chid;
        u8 ids_valid:1; /* cssid,iid,chid */
        u8 dev_addr_is_registered:1;
-       u8 open_when_online:1;
        u8 promisc_mode:1;
        u8 use_v1_blkt:1;
        u8 is_vm_nic:1;
index 1d5b207c2b9e97148e4aa31a8bd9938552004cba..cd783290bde5ec5cd6e63055210d628d026427ac 100644 (file)
@@ -5373,8 +5373,6 @@ int qeth_set_offline(struct qeth_card *card, const struct qeth_discipline *disc,
        qeth_clear_ipacmd_list(card);
 
        rtnl_lock();
-       card->info.open_when_online = card->dev->flags & IFF_UP;
-       dev_close(card->dev);
        netif_device_detach(card->dev);
        netif_carrier_off(card->dev);
        rtnl_unlock();
index 9f13ed170a437b0314fe5c1708fd815dac271f46..75910c0bcc2bc358c05dcae87bf5a47cc41c7315 100644 (file)
@@ -2388,9 +2388,12 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok)
                qeth_enable_hw_features(dev);
                qeth_l2_enable_brport_features(card);
 
-               if (card->info.open_when_online) {
-                       card->info.open_when_online = 0;
-                       dev_open(dev, NULL);
+               if (netif_running(dev)) {
+                       local_bh_disable();
+                       napi_schedule(&card->napi);
+                       /* kick-start the NAPI softirq: */
+                       local_bh_enable();
+                       qeth_l2_set_rx_mode(dev);
                }
                rtnl_unlock();
        }
index af4e60d2917e9d6e8e1f9f412f24479f8a7156fe..b92a32b4b1141670cc2f3c2e8b91a8e1d526b26a 100644 (file)
@@ -2018,9 +2018,11 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok)
                netif_device_attach(dev);
                qeth_enable_hw_features(dev);
 
-               if (card->info.open_when_online) {
-                       card->info.open_when_online = 0;
-                       dev_open(dev, NULL);
+               if (netif_running(dev)) {
+                       local_bh_disable();
+                       napi_schedule(&card->napi);
+                       /* kick-start the NAPI softirq: */
+                       local_bh_enable();
                }
                rtnl_unlock();
        }
index f21307537829ba91e67c20d0aa91d5c285baff1e..4f0d0e55f0d46196613d6f01090a6fec3cf8d6f2 100644 (file)
@@ -534,8 +534,7 @@ static void zfcp_fc_adisc_handler(void *data)
 
        /* re-init to undo drop from zfcp_fc_adisc() */
        port->d_id = ntoh24(adisc_resp->adisc_port_id);
-       /* port is good, unblock rport without going through erp */
-       zfcp_scsi_schedule_rport_register(port);
+       /* port is still good, nothing to do */
  out:
        atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
        put_device(&port->dev);
@@ -595,9 +594,6 @@ void zfcp_fc_link_test_work(struct work_struct *work)
        int retval;
 
        set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */
-       get_device(&port->dev);
-       port->rport_task = RPORT_DEL;
-       zfcp_scsi_rport_work(&port->rport_work);
 
        /* only issue one test command at one time per port */
        if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST)
index e1e4f9d1088798783e5e9ae64d02626eb2a5d629..857be0f3ae5b9809b4ed048a05bf0868cfc9a4f7 100644 (file)
@@ -1598,7 +1598,7 @@ NCR_700_intr(int irq, void *dev_id)
                                printk("scsi%d (%d:%d) PHASE MISMATCH IN SEND MESSAGE %d remain, return %p[%04x], phase %s\n", host->host_no, pun, lun, count, (void *)temp, temp - hostdata->pScript, sbcl_to_string(NCR_700_readb(host, SBCL_REG)));
 #endif
                                resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch;
-                       } else if(dsp >= to32bit(&slot->pSG[0].ins) &&
+                       } else if (slot && dsp >= to32bit(&slot->pSG[0].ins) &&
                                  dsp <= to32bit(&slot->pSG[NCR_700_SG_SEGMENTS].ins)) {
                                int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff;
                                int SGcount = (dsp - to32bit(&slot->pSG[0].ins))/sizeof(struct NCR_700_SG_List);
index d82de34f6fd73fd1f8efef8f94a9e9da2476429b..e51e92f932fa8bc2d491451589c682bd7652e250 100644 (file)
@@ -27,7 +27,7 @@
 
 #define DRV_NAME               "fnic"
 #define DRV_DESCRIPTION                "Cisco FCoE HBA Driver"
-#define DRV_VERSION            "1.6.0.54"
+#define DRV_VERSION            "1.6.0.55"
 #define PFX                    DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
index 26dbd347156ef90eec1f6c99ec532448f63d73f0..be89ce96df46c8104f58e4f930825db6c05400b5 100644 (file)
@@ -2139,7 +2139,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
                                     bool new_sc)
 
 {
-       int ret = SUCCESS;
+       int ret = 0;
        struct fnic_pending_aborts_iter_data iter_data = {
                .fnic = fnic,
                .lun_dev = lr_sc->device,
@@ -2159,9 +2159,11 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
 
        /* walk again to check, if IOs are still pending in fw */
        if (fnic_is_abts_pending(fnic, lr_sc))
-               ret = FAILED;
+               ret = 1;
 
 clean_pending_aborts_end:
+       FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+                       "%s: exit status: %d\n", __func__, ret);
        return ret;
 }
 
index a62e091894f6e5951fd4d8a2a26b330ab0e4dd6f..d26941b131fdb81e6bc9fe48ccc57b75a0055af5 100644 (file)
@@ -109,8 +109,6 @@ lpfc_sli4_set_rsp_sgl_last(struct lpfc_hba *phba,
        }
 }
 
-#define LPFC_INVALID_REFTAG ((u32)-1)
-
 /**
  * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
  * @phba: The Hba for which this call is being executed.
@@ -978,8 +976,6 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
 
        sgpe = scsi_prot_sglist(sc);
        lba = scsi_prot_ref_tag(sc);
-       if (lba == LPFC_INVALID_REFTAG)
-               return 0;
 
        /* First check if we need to match the LBA */
        if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) {
@@ -1560,8 +1556,6 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
 
        /* extract some info from the scsi command for pde*/
        reftag = scsi_prot_ref_tag(sc);
-       if (reftag == LPFC_INVALID_REFTAG)
-               goto out;
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
@@ -1723,8 +1717,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        /* extract some info from the scsi command */
        blksize = scsi_prot_interval(sc);
        reftag = scsi_prot_ref_tag(sc);
-       if (reftag == LPFC_INVALID_REFTAG)
-               goto out;
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
@@ -1953,8 +1945,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
 
        /* extract some info from the scsi command for pde*/
        reftag = scsi_prot_ref_tag(sc);
-       if (reftag == LPFC_INVALID_REFTAG)
-               goto out;
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
@@ -2154,8 +2144,6 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        /* extract some info from the scsi command */
        blksize = scsi_prot_interval(sc);
        reftag = scsi_prot_ref_tag(sc);
-       if (reftag == LPFC_INVALID_REFTAG)
-               goto out;
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
@@ -2746,8 +2734,6 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
 
                src = (struct scsi_dif_tuple *)sg_virt(sgpe);
                start_ref_tag = scsi_prot_ref_tag(cmd);
-               if (start_ref_tag == LPFC_INVALID_REFTAG)
-                       goto out;
                start_app_tag = src->app_tag;
                len = sgpe->length;
                while (src && protsegcnt) {
@@ -3493,11 +3479,11 @@ err:
                             scsi_cmnd->sc_data_direction);
 
        lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
-                       "9084 Cannot setup S/G List for HBA"
-                       "IO segs %d/%d SGL %d SCSI %d: %d %d\n",
+                       "9084 Cannot setup S/G List for HBA "
+                       "IO segs %d/%d SGL %d SCSI %d: %d %d %d\n",
                        lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
                        phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt,
-                       prot_group_type, num_sge);
+                       prot_group_type, num_sge, ret);
 
        lpfc_cmd->seg_cnt = 0;
        lpfc_cmd->prot_seg_cnt = 0;
index 2e886c1d867d4c66d387900b24baabb9b92d26c5..4995e1ef4e0e51da6b0f3d47c88e846b0598a48a 100644 (file)
@@ -1181,7 +1181,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
                pm80xx_set_thermal_config(pm8001_ha);
        }
 
-       if (pm8001_init_sas_add(pm8001_ha))
+       rc = pm8001_init_sas_add(pm8001_ha);
+       if (rc)
                goto err_out_shost;
        /* phy setting support for motherboard controller */
        rc = pm8001_configure_phy_settings(pm8001_ha);
index 2a31ddc99dde5becdd57278c02e776ca1d35f992..7825765c936cd651b276af2507799664b5cedeb1 100644 (file)
@@ -31,6 +31,7 @@ static void qedf_remove(struct pci_dev *pdev);
 static void qedf_shutdown(struct pci_dev *pdev);
 static void qedf_schedule_recovery_handler(void *dev);
 static void qedf_recovery_handler(struct work_struct *work);
+static int qedf_suspend(struct pci_dev *pdev, pm_message_t state);
 
 /*
  * Driver module parameters.
@@ -3271,6 +3272,7 @@ static struct pci_driver qedf_pci_driver = {
        .probe = qedf_probe,
        .remove = qedf_remove,
        .shutdown = qedf_shutdown,
+       .suspend = qedf_suspend,
 };
 
 static int __qedf_probe(struct pci_dev *pdev, int mode)
@@ -4000,6 +4002,22 @@ static void qedf_shutdown(struct pci_dev *pdev)
        __qedf_remove(pdev, QEDF_MODE_NORMAL);
 }
 
+static int qedf_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct qedf_ctx *qedf;
+
+       if (!pdev) {
+               QEDF_ERR(NULL, "pdev is NULL.\n");
+               return -ENODEV;
+       }
+
+       qedf = pci_get_drvdata(pdev);
+
+       QEDF_ERR(&qedf->dbg_ctx, "%s: Device does not support suspend operation\n", __func__);
+
+       return -EPERM;
+}
+
 /*
  * Recovery handler code
  */
index 450522b204d62b9e78c29069f8a94e6417c50e6f..cd0180b1f5b9dad5d8be7019ba0e2675430f543e 100644 (file)
@@ -69,6 +69,7 @@ static struct nvm_iscsi_block *qedi_get_nvram_block(struct qedi_ctx *qedi);
 static void qedi_recovery_handler(struct work_struct *work);
 static void qedi_schedule_hw_err_handler(void *dev,
                                         enum qed_hw_err_type err_type);
+static int qedi_suspend(struct pci_dev *pdev, pm_message_t state);
 
 static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle)
 {
@@ -1976,8 +1977,9 @@ static int qedi_cpu_offline(unsigned int cpu)
        struct qedi_percpu_s *p = this_cpu_ptr(&qedi_percpu);
        struct qedi_work *work, *tmp;
        struct task_struct *thread;
+       unsigned long flags;
 
-       spin_lock_bh(&p->p_work_lock);
+       spin_lock_irqsave(&p->p_work_lock, flags);
        thread = p->iothread;
        p->iothread = NULL;
 
@@ -1988,7 +1990,7 @@ static int qedi_cpu_offline(unsigned int cpu)
                        kfree(work);
        }
 
-       spin_unlock_bh(&p->p_work_lock);
+       spin_unlock_irqrestore(&p->p_work_lock, flags);
        if (thread)
                kthread_stop(thread);
        return 0;
@@ -2510,6 +2512,22 @@ static void qedi_shutdown(struct pci_dev *pdev)
        __qedi_remove(pdev, QEDI_MODE_SHUTDOWN);
 }
 
+static int qedi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct qedi_ctx *qedi;
+
+       if (!pdev) {
+               QEDI_ERR(NULL, "pdev is NULL.\n");
+               return -ENODEV;
+       }
+
+       qedi = pci_get_drvdata(pdev);
+
+       QEDI_ERR(&qedi->dbg_ctx, "%s: Device does not support suspend operation\n", __func__);
+
+       return -EPERM;
+}
+
 static int __qedi_probe(struct pci_dev *pdev, int mode)
 {
        struct qedi_ctx *qedi;
@@ -2868,6 +2886,7 @@ static struct pci_driver qedi_pci_driver = {
        .remove = qedi_remove,
        .shutdown = qedi_shutdown,
        .err_handler = &qedi_err_handler,
+       .suspend = qedi_suspend,
 };
 
 static int __init qedi_init(void)
index 898a0bdf8df6702666f865dbe9371851973f8068..711252e52d8e1f08d65c0801d4c53f70182d0134 100644 (file)
@@ -248,6 +248,7 @@ int raid_component_add(struct raid_template *r,struct device *raid_dev,
        return 0;
 
 err_out:
+       put_device(&rc->dev);
        list_del(&rc->node);
        rd->component_count--;
        put_device(component_dev);
index 4a6eb1741be0d2b56725bc7d5427cc59a325c49e..41f23cd0bfb45d74c058183508c374a31b7546c1 100644 (file)
@@ -406,7 +406,7 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
                               size_t length, loff_t *ppos)
 {
        int host, channel, id, lun;
-       char *buffer, *p;
+       char *buffer, *end, *p;
        int err;
 
        if (!buf || length > PAGE_SIZE)
@@ -421,10 +421,14 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
                goto out;
 
        err = -EINVAL;
-       if (length < PAGE_SIZE)
-               buffer[length] = '\0';
-       else if (buffer[PAGE_SIZE-1])
-               goto out;
+       if (length < PAGE_SIZE) {
+               end = buffer + length;
+               *end = '\0';
+       } else {
+               end = buffer + PAGE_SIZE - 1;
+               if (*end)
+                       goto out;
+       }
 
        /*
         * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi
@@ -433,10 +437,10 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
        if (!strncmp("scsi add-single-device", buffer, 22)) {
                p = buffer + 23;
 
-               host = simple_strtoul(p, &p, 0);
-               channel = simple_strtoul(p + 1, &p, 0);
-               id = simple_strtoul(p + 1, &p, 0);
-               lun = simple_strtoul(p + 1, &p, 0);
+               host    = (p     < end) ? simple_strtoul(p, &p, 0) : 0;
+               channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+               id      = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+               lun     = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
 
                err = scsi_add_single_device(host, channel, id, lun);
 
@@ -447,10 +451,10 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
        } else if (!strncmp("scsi remove-single-device", buffer, 25)) {
                p = buffer + 26;
 
-               host = simple_strtoul(p, &p, 0);
-               channel = simple_strtoul(p + 1, &p, 0);
-               id = simple_strtoul(p + 1, &p, 0);
-               lun = simple_strtoul(p + 1, &p, 0);
+               host    = (p     < end) ? simple_strtoul(p, &p, 0) : 0;
+               channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+               id      = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+               lun     = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
 
                err = scsi_remove_single_device(host, channel, id, lun);
        }
index 68b12afa07219a7bb692568438816bacd44d3d24..3c668cfb146d390fa23b2bc1d13c7841cec79fc5 100644 (file)
@@ -3876,7 +3876,7 @@ static int sd_suspend_runtime(struct device *dev)
 static int sd_resume(struct device *dev)
 {
        struct scsi_disk *sdkp = dev_get_drvdata(dev);
-       int ret;
+       int ret = 0;
 
        if (!sdkp)      /* E.g.: runtime resume at the start of sd_probe() */
                return 0;
@@ -3884,8 +3884,11 @@ static int sd_resume(struct device *dev)
        if (!sdkp->device->manage_start_stop)
                return 0;
 
-       sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
-       ret = sd_start_stop_device(sdkp, 1);
+       if (!sdkp->device->no_start_on_resume) {
+               sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+               ret = sd_start_stop_device(sdkp, 1);
+       }
+
        if (!ret)
                opal_unlock_from_suspend(sdkp->opal_dev);
        return ret;
index 3e2e5783924d03caed2efa21587d485d54c9acc4..e429ad23c396dab72d68434d57936dc1b7b6fbb4 100644 (file)
@@ -303,6 +303,7 @@ snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid)
                              "Snic Tgt: device_add, with err = %d\n",
                              ret);
 
+               put_device(&tgt->dev);
                put_device(&snic->shost->shost_gendev);
                spin_lock_irqsave(snic->shost->host_lock, flags);
                list_del(&tgt->list);
index 7f12d931fe7c1464c4e39d123666f0444efc5417..047ffaf7d42a9e7c37bc541f12e24df00ae497c5 100644 (file)
@@ -366,6 +366,7 @@ static void storvsc_on_channel_callback(void *context);
 #define STORVSC_FC_MAX_LUNS_PER_TARGET                 255
 #define STORVSC_FC_MAX_TARGETS                         128
 #define STORVSC_FC_MAX_CHANNELS                                8
+#define STORVSC_FC_MAX_XFER_SIZE                       ((u32)(512 * 1024))
 
 #define STORVSC_IDE_MAX_LUNS_PER_TARGET                        64
 #define STORVSC_IDE_MAX_TARGETS                                1
@@ -1673,10 +1674,6 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
  */
 static enum scsi_timeout_action storvsc_eh_timed_out(struct scsi_cmnd *scmnd)
 {
-#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
-       if (scmnd->device->host->transportt == fc_transport_template)
-               return fc_eh_timed_out(scmnd);
-#endif
        return SCSI_EH_RESET_TIMER;
 }
 
@@ -2006,6 +2003,9 @@ static int storvsc_probe(struct hv_device *device,
         * protecting it from any weird value.
         */
        max_xfer_bytes = round_down(stor_device->max_transfer_bytes, HV_HYP_PAGE_SIZE);
+       if (is_fc)
+               max_xfer_bytes = min(max_xfer_bytes, STORVSC_FC_MAX_XFER_SIZE);
+
        /* max_hw_sectors_kb */
        host->max_sectors = max_xfer_bytes >> 9;
        /*
index 1ca140356a084d4c7de9b7331c271e6b7d6355af..3f759121dc00a44a24de23e39540080815cb7c94 100644 (file)
@@ -137,6 +137,7 @@ static int __init aspeed_socinfo_init(void)
 
        soc_dev = soc_device_register(attrs);
        if (IS_ERR(soc_dev)) {
+               kfree(attrs->machine);
                kfree(attrs->soc_id);
                kfree(attrs->serial_number);
                kfree(attrs);
index ef8b24fd18518a4db9df7013f43312adf269b060..59123e1f27acb89cbc3ca0fbee81760cb791fb9b 100644 (file)
@@ -524,7 +524,7 @@ static ssize_t aspeed_uart_routing_store(struct device *dev,
        struct aspeed_uart_routing_selector *sel = to_routing_selector(attr);
        int val;
 
-       val = match_string(sel->options, -1, buf);
+       val = __sysfs_match_string(sel->options, -1, buf);
        if (val < 0) {
                dev_err(dev, "invalid value \"%s\"\n", buf);
                return -EINVAL;
index 870aecc0202aebd88c9af6d62a4cb94aa8f57401..1c1fcab4979a4a979f96acf1700945c6e0389610 100644 (file)
@@ -164,7 +164,7 @@ static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc)
        clk_hsio_pll->hw.init = &init;
 
        hw = &clk_hsio_pll->hw;
-       ret = devm_clk_hw_register(bc->dev, hw);
+       ret = devm_clk_hw_register(bc->bus_power_dev, hw);
        if (ret)
                return ret;
 
index 013f1633f082764ed2f5c703a5665afb0c087fb6..2f00fc3bf274a33255b1308de7772f1752c2c638 100644 (file)
@@ -57,10 +57,10 @@ static int rapl_mmio_cpu_down_prep(unsigned int cpu)
 
 static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
 {
-       if (!ra->reg)
+       if (!ra->reg.mmio)
                return -EINVAL;
 
-       ra->value = readq((void __iomem *)ra->reg);
+       ra->value = readq(ra->reg.mmio);
        ra->value &= ra->mask;
        return 0;
 }
@@ -69,13 +69,13 @@ static int rapl_mmio_write_raw(int cpu, struct reg_action *ra)
 {
        u64 val;
 
-       if (!ra->reg)
+       if (!ra->reg.mmio)
                return -EINVAL;
 
-       val = readq((void __iomem *)ra->reg);
+       val = readq(ra->reg.mmio);
        val &= ~ra->mask;
        val |= ra->value;
-       writeq(val, (void __iomem *)ra->reg);
+       writeq(val, ra->reg.mmio);
        return 0;
 }
 
@@ -92,13 +92,13 @@ int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc
        for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) {
                for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++)
                        if (rapl_regs->regs[domain][reg])
-                               rapl_mmio_priv.regs[domain][reg] =
-                                               (u64)proc_priv->mmio_base +
+                               rapl_mmio_priv.regs[domain][reg].mmio =
+                                               proc_priv->mmio_base +
                                                rapl_regs->regs[domain][reg];
                rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain];
        }
        rapl_mmio_priv.type = RAPL_IF_MMIO;
-       rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit;
+       rapl_mmio_priv.reg_unit.mmio = proc_priv->mmio_base + rapl_regs->reg_unit;
 
        rapl_mmio_priv.read_raw = rapl_mmio_read_raw;
        rapl_mmio_priv.write_raw = rapl_mmio_write_raw;
index cc2b5e81c6205c51ba7dcddc9bfaaa37bb90d14d..a59700593d326d3e04a3b1e5b158a32b098ee802 100644 (file)
@@ -348,7 +348,8 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id)
        struct thermal_trip trip;
 
        /* Ignore disabled trip points */
-       if (test_bit(trip_id, &tz->trips_disabled))
+       if (test_bit(trip_id, &tz->trips_disabled) ||
+           trip.temperature == THERMAL_TEMP_INVALID)
                return;
 
        __thermal_zone_get_trip(tz, trip_id, &trip);
@@ -496,6 +497,25 @@ void thermal_zone_device_update(struct thermal_zone_device *tz,
 }
 EXPORT_SYMBOL_GPL(thermal_zone_device_update);
 
+/**
+ * thermal_zone_device_exec - Run a callback under the zone lock.
+ * @tz: Thermal zone.
+ * @cb: Callback to run.
+ * @data: Data to pass to the callback.
+ */
+void thermal_zone_device_exec(struct thermal_zone_device *tz,
+                             void (*cb)(struct thermal_zone_device *,
+                                        unsigned long),
+                             unsigned long data)
+{
+       mutex_lock(&tz->lock);
+
+       cb(tz, data);
+
+       mutex_unlock(&tz->lock);
+}
+EXPORT_SYMBOL_GPL(thermal_zone_device_exec);
+
 static void thermal_zone_device_check(struct work_struct *work)
 {
        struct thermal_zone_device *tz = container_of(work, struct
index 17c1bbed734d398756a1ae959c15f139a6ec9ac5..04513f9fbfa1803b93c669a3abd86e5d4ce4cb5c 100644 (file)
@@ -54,10 +54,6 @@ int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *,
 int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *),
                              void *thermal_governor);
 
-int __for_each_thermal_trip(struct thermal_zone_device *,
-                           int (*cb)(struct thermal_trip *, void *),
-                           void *);
-
 struct thermal_zone_device *thermal_zone_get_by_id(int id);
 
 struct thermal_attr {
index 907f3a4d7bc8c121eb214158b95658d96d1f8eec..53115cfdfd42a4318f52d648913c1043aa8d4c5c 100644 (file)
@@ -9,28 +9,26 @@
  */
 #include "thermal_core.h"
 
-int __for_each_thermal_trip(struct thermal_zone_device *tz,
-                           int (*cb)(struct thermal_trip *, void *),
-                           void *data)
+int for_each_thermal_trip(struct thermal_zone_device *tz,
+                         int (*cb)(struct thermal_trip *, void *),
+                         void *data)
 {
        int i, ret;
-       struct thermal_trip trip;
 
        lockdep_assert_held(&tz->lock);
 
-       for (i = 0; i < tz->num_trips; i++) {
-
-               ret = __thermal_zone_get_trip(tz, i, &trip);
-               if (ret)
-                       return ret;
+       if (!tz->trips)
+               return -ENODATA;
 
-               ret = cb(&trip, data);
+       for (i = 0; i < tz->num_trips; i++) {
+               ret = cb(&tz->trips[i], data);
                if (ret)
                        return ret;
        }
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(for_each_thermal_trip);
 
 int thermal_zone_get_num_trips(struct thermal_zone_device *tz)
 {
index 62b26b7998fd88109003e84b8b359ea731fc997a..3fb4553a6442b48e09afbbd3945e358d6caa0f8c 100644 (file)
@@ -1964,6 +1964,8 @@ unlock:
 
        pm_runtime_mark_last_busy(&tb->dev);
        pm_runtime_put_autosuspend(&tb->dev);
+
+       kfree(ev);
 }
 
 static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port)
index 1269f417515bbc8979f9c8279e9f32c26fa8770c..0dfd1e083994e6d222efda74f7794d7cdc22c6f3 100644 (file)
@@ -579,7 +579,9 @@ int tb_switch_tmu_disable(struct tb_switch *sw)
                 * uni-directional mode and we don't want to change it's TMU
                 * mode.
                 */
-               tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]);
+               ret = tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]);
+               if (ret)
+                       return ret;
 
                tb_port_tmu_time_sync_disable(up);
                ret = tb_port_tmu_time_sync_disable(down);
index 341abaed4ce2c093d83fb1453b9a7ec20610eb7b..069de553127c4394db86a4c111ccb8b422433cdc 100644 (file)
@@ -164,6 +164,9 @@ config LEGACY_TIOCSTI
          userspace depends on this functionality to continue operating
          normally.
 
+         Processes which run with CAP_SYS_ADMIN, such as BRLTTY, can
+         use TIOCSTI even when this is set to N.
+
          This functionality can be changed at runtime with the
          dev.tty.legacy_tiocsti sysctl. This configuration option sets
          the default value of the sysctl.
index 1cdefac4dd1b5dcc03721b342036f946b7ef2a3c..739f522cb893c078401a39559ed57e82c6c2bbaa 100644 (file)
@@ -3042,12 +3042,13 @@ static void gsm_error(struct gsm_mux *gsm)
 static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
 {
        int i;
-       struct gsm_dlci *dlci = gsm->dlci[0];
+       struct gsm_dlci *dlci;
        struct gsm_msg *txq, *ntxq;
 
        gsm->dead = true;
        mutex_lock(&gsm->mutex);
 
+       dlci = gsm->dlci[0];
        if (dlci) {
                if (disc && dlci->state != DLCI_CLOSED) {
                        gsm_dlci_begin_close(dlci);
index 914e0e6251bfca59d2c060dc804a7b87d8f889ba..3449f8790e462e269df4c454fb37bfde330bed7e 100644 (file)
@@ -497,6 +497,7 @@ static struct uart_8250_port *serial8250_setup_port(int index)
 
        up = &serial8250_ports[index];
        up->port.line = index;
+       up->port.port_id = index;
 
        serial8250_init_port(up);
        if (!base_ops)
@@ -1040,6 +1041,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
                        uart_remove_one_port(&serial8250_reg, &uart->port);
 
                uart->port.ctrl_id      = up->port.ctrl_id;
+               uart->port.port_id      = up->port.port_id;
                uart->port.iobase       = up->port.iobase;
                uart->port.membase      = up->port.membase;
                uart->port.irq          = up->port.irq;
@@ -1202,6 +1204,7 @@ void serial8250_unregister_port(int line)
                uart->port.flags &= ~UPF_BOOT_AUTOCONF;
                uart->port.type = PORT_UNKNOWN;
                uart->port.dev = &serial8250_isa_devs->dev;
+               uart->port.port_id = line;
                uart->capabilities = 0;
                serial8250_init_port(uart);
                serial8250_apply_quirks(uart);
index 16aeb14201378f01c755cfbb14028632d210524e..483bb552cdc403469837fe092c9ba2105a196b94 100644 (file)
@@ -703,9 +703,6 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
 
 static void serial8250_clear_IER(struct uart_8250_port *up)
 {
-       /* Port locked to synchronize UART_IER access against the console. */
-       lockdep_assert_held_once(&up->port.lock);
-
        if (up->capabilities & UART_CAP_UUE)
                serial_out(up, UART_IER, UART_IER_UUE);
        else
@@ -3278,6 +3275,7 @@ void serial8250_init_port(struct uart_8250_port *up)
 
        spin_lock_init(&port->lock);
        port->ctrl_id = 0;
+       port->pm = NULL;
        port->ops = &serial8250_pops;
        port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
 
index 4d80fae20177948fd43652a4f1c55a7b262dba0d..c569a08b5b1991e1e95779a7c11126d9324f1259 100644 (file)
@@ -1139,8 +1139,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
                unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
 
                if (sr & (UARTSTAT_PE | UARTSTAT_FE)) {
-                       /* Read DR to clear the error flags */
-                       lpuart32_read(&sport->port, UARTDATA);
+                       /* Clear the error flags */
+                       lpuart32_write(&sport->port, sr, UARTSTAT);
 
                        if (sr & UARTSTAT_PE)
                                sport->port.icount.parity++;
index 9faac0ff6b8957dff48546f48c056396a3d4bcf6..c74c548f0db62ae97ffdfbe33390bac50c412862 100644 (file)
@@ -16,6 +16,7 @@ struct device;
 
 struct serial_ctrl_device {
        struct device dev;
+       struct ida port_ida;
 };
 
 struct serial_port_device {
index 6ff59c89d867d0cb73f7a00ad2729dc98cbd7621..3dfcf20c4eb68c99b71ab06e7c1c1c8925f4261a 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/container_of.h>
 #include <linux/device.h>
+#include <linux/idr.h>
 #include <linux/module.h>
 #include <linux/serial_core.h>
 #include <linux/slab.h>
 
 static bool serial_base_initialized;
 
+static const struct device_type serial_ctrl_type = {
+       .name = "ctrl",
+};
+
+static const struct device_type serial_port_type = {
+       .name = "port",
+};
+
 static int serial_base_match(struct device *dev, struct device_driver *drv)
 {
-       int len = strlen(drv->name);
+       if (dev->type == &serial_ctrl_type &&
+           str_has_prefix(drv->name, serial_ctrl_type.name))
+               return 1;
 
-       return !strncmp(dev_name(dev), drv->name, len);
+       if (dev->type == &serial_port_type &&
+           str_has_prefix(drv->name, serial_port_type.name))
+               return 1;
+
+       return 0;
 }
 
 static struct bus_type serial_base_bus_type = {
@@ -48,7 +63,8 @@ static int serial_base_device_init(struct uart_port *port,
                                   struct device *parent_dev,
                                   const struct device_type *type,
                                   void (*release)(struct device *dev),
-                                  int id)
+                                  unsigned int ctrl_id,
+                                  unsigned int port_id)
 {
        device_initialize(dev);
        dev->type = type;
@@ -61,12 +77,15 @@ static int serial_base_device_init(struct uart_port *port,
                return -EPROBE_DEFER;
        }
 
-       return dev_set_name(dev, "%s.%s.%d", type->name, dev_name(port->dev), id);
-}
+       if (type == &serial_ctrl_type)
+               return dev_set_name(dev, "%s:%d", dev_name(port->dev), ctrl_id);
 
-static const struct device_type serial_ctrl_type = {
-       .name = "ctrl",
-};
+       if (type == &serial_port_type)
+               return dev_set_name(dev, "%s:%d.%d", dev_name(port->dev),
+                                   ctrl_id, port_id);
+
+       return -EINVAL;
+}
 
 static void serial_base_ctrl_release(struct device *dev)
 {
@@ -81,6 +100,7 @@ void serial_base_ctrl_device_remove(struct serial_ctrl_device *ctrl_dev)
                return;
 
        device_del(&ctrl_dev->dev);
+       put_device(&ctrl_dev->dev);
 }
 
 struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
@@ -93,10 +113,12 @@ struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
        if (!ctrl_dev)
                return ERR_PTR(-ENOMEM);
 
+       ida_init(&ctrl_dev->port_ida);
+
        err = serial_base_device_init(port, &ctrl_dev->dev,
                                      parent, &serial_ctrl_type,
                                      serial_base_ctrl_release,
-                                     port->ctrl_id);
+                                     port->ctrl_id, 0);
        if (err)
                goto err_put_device;
 
@@ -112,10 +134,6 @@ err_put_device:
        return ERR_PTR(err);
 }
 
-static const struct device_type serial_port_type = {
-       .name = "port",
-};
-
 static void serial_base_port_release(struct device *dev)
 {
        struct serial_port_device *port_dev = to_serial_base_port_device(dev);
@@ -127,16 +145,31 @@ struct serial_port_device *serial_base_port_add(struct uart_port *port,
                                                struct serial_ctrl_device *ctrl_dev)
 {
        struct serial_port_device *port_dev;
+       int min = 0, max = -1;  /* Use -1 for max to apply IDA defaults */
        int err;
 
        port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
        if (!port_dev)
                return ERR_PTR(-ENOMEM);
 
+       /* Device driver specified port_id vs automatic assignment? */
+       if (port->port_id) {
+               min = port->port_id;
+               max = port->port_id;
+       }
+
+       err = ida_alloc_range(&ctrl_dev->port_ida, min, max, GFP_KERNEL);
+       if (err < 0) {
+               kfree(port_dev);
+               return ERR_PTR(err);
+       }
+
+       port->port_id = err;
+
        err = serial_base_device_init(port, &port_dev->dev,
                                      &ctrl_dev->dev, &serial_port_type,
                                      serial_base_port_release,
-                                     port->line);
+                                     port->ctrl_id, port->port_id);
        if (err)
                goto err_put_device;
 
@@ -150,16 +183,25 @@ struct serial_port_device *serial_base_port_add(struct uart_port *port,
 
 err_put_device:
        put_device(&port_dev->dev);
+       ida_free(&ctrl_dev->port_ida, port->port_id);
 
        return ERR_PTR(err);
 }
 
 void serial_base_port_device_remove(struct serial_port_device *port_dev)
 {
+       struct serial_ctrl_device *ctrl_dev;
+       struct device *parent;
+
        if (!port_dev)
                return;
 
+       parent = port_dev->dev.parent;
+       ctrl_dev = to_serial_base_ctrl_device(parent);
+
        device_del(&port_dev->dev);
+       ida_free(&ctrl_dev->port_ida, port_dev->port->port_id);
+       put_device(&port_dev->dev);
 }
 
 static int serial_base_init(void)
index f8a5e79ed3b4e4c171a2025915513d8d72106f09..ab0652d8705ac913a18186a411ad432a83ab3a9c 100644 (file)
@@ -359,7 +359,7 @@ static int ufs_renesas_init(struct ufs_hba *hba)
 {
        struct ufs_renesas_priv *priv;
 
-       priv = devm_kmalloc(hba->dev, sizeof(*priv), GFP_KERNEL);
+       priv = devm_kzalloc(hba->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
        ufshcd_set_variant(hba, priv);
index 766005d20baefde32a69e78a84fc6f39e33b9241..501e8bc9738eba54836dcc2b97f83c36e791f1e9 100644 (file)
@@ -42,6 +42,7 @@ struct usb_conn_info {
 
        struct power_supply_desc desc;
        struct power_supply *charger;
+       bool initial_detection;
 };
 
 /*
@@ -86,11 +87,13 @@ static void usb_conn_detect_cable(struct work_struct *work)
        dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n",
                usb_role_string(info->last_role), usb_role_string(role), id, vbus);
 
-       if (info->last_role == role) {
+       if (!info->initial_detection && info->last_role == role) {
                dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role));
                return;
        }
 
+       info->initial_detection = false;
+
        if (info->last_role == USB_ROLE_HOST && info->vbus)
                regulator_disable(info->vbus);
 
@@ -258,6 +261,7 @@ static int usb_conn_probe(struct platform_device *pdev)
        device_set_wakeup_capable(&pdev->dev, true);
 
        /* Perform initial detection */
+       info->initial_detection = true;
        usb_conn_queue_dwork(info, 0);
 
        return 0;
index 5fd067151fbf5745c65e54cce5519c279154e0da..858fe4c299b7af2609677eec6079e53022930bad 100644 (file)
@@ -4455,9 +4455,14 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
        u32 count;
 
        if (pm_runtime_suspended(dwc->dev)) {
+               dwc->pending_events = true;
+               /*
+                * Trigger runtime resume. The get() function will be balanced
+                * after processing the pending events in dwc3_process_pending
+                * events().
+                */
                pm_runtime_get(dwc->dev);
                disable_irq_nosync(dwc->irq_gadget);
-               dwc->pending_events = true;
                return IRQ_HANDLED;
        }
 
@@ -4718,6 +4723,8 @@ void dwc3_gadget_process_pending_events(struct dwc3 *dwc)
 {
        if (dwc->pending_events) {
                dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf);
+               dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf);
+               pm_runtime_put(dwc->dev);
                dwc->pending_events = false;
                enable_irq(dwc->irq_gadget);
        }
index cd58f2a4e7f34de145840e40de42c61f6f19b0a6..7d49d8a0b00c2c2c85d717fd104f37752dc4584e 100644 (file)
@@ -822,6 +822,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
  * usb_gadget_activate() is called.  For example, user mode components may
  * need to be activated before the system can talk to hosts.
  *
+ * This routine may sleep; it must not be called in interrupt context
+ * (such as from within a gadget driver's disconnect() callback).
+ *
  * Returns zero on success, else negative errno.
  */
 int usb_gadget_deactivate(struct usb_gadget *gadget)
@@ -860,6 +863,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate);
  * This routine activates gadget which was previously deactivated with
  * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed.
  *
+ * This routine may sleep; it must not be called in interrupt context.
+ *
  * Returns zero on success, else negative errno.
  */
 int usb_gadget_activate(struct usb_gadget *gadget)
@@ -1638,7 +1643,11 @@ static void gadget_unbind_driver(struct device *dev)
        usb_gadget_disable_async_callbacks(udc);
        if (gadget->irq)
                synchronize_irq(gadget->irq);
+       mutex_unlock(&udc->connect_lock);
+
        udc->driver->unbind(gadget);
+
+       mutex_lock(&udc->connect_lock);
        usb_gadget_udc_stop_locked(udc);
        mutex_unlock(&udc->connect_lock);
 
index 5e912dd29b4c99dd85600cb3d4c8f187cc0146da..115f05a6201a16883f53a3d271f48adc05acd983 100644 (file)
@@ -318,7 +318,8 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
        rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
                command, 0xc0, 0, 1, data, 2);
 
-       usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
+       if (rc == USB_STOR_XFER_GOOD)
+               usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
 
        return rc;
 }
@@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us)
 static int alauda_check_media(struct us_data *us)
 {
        struct alauda_info *info = (struct alauda_info *) us->extra;
-       unsigned char status[2];
+       unsigned char *status = us->iobuf;
+       int rc;
 
-       alauda_get_media_status(us, status);
+       rc = alauda_get_media_status(us, status);
+       if (rc != USB_STOR_XFER_GOOD) {
+               status[0] = 0xF0;       /* Pretend there's no media */
+               status[1] = 0;
+       }
 
        /* Check for no media or door open */
        if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
index 66de880b28d01a60d592a490d820aa78f87a9aa0..cdf8261e22dbd3ff45c9ff758bd00e493e737f36 100644 (file)
@@ -60,6 +60,7 @@ struct dp_altmode {
 
        enum dp_state state;
        bool hpd;
+       bool pending_hpd;
 
        struct mutex lock; /* device lock */
        struct work_struct work;
@@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
                dp->state = DP_STATE_EXIT;
        } else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) {
                ret = dp_altmode_configure(dp, con);
-               if (!ret)
+               if (!ret) {
                        dp->state = DP_STATE_CONFIGURE;
+                       if (dp->hpd != hpd) {
+                               dp->hpd = hpd;
+                               dp->pending_hpd = true;
+                       }
+               }
        } else {
                if (dp->hpd != hpd) {
                        drm_connector_oob_hotplug_event(dp->connector_fwnode);
@@ -161,6 +167,16 @@ static int dp_altmode_configured(struct dp_altmode *dp)
 {
        sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
        sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");
+       /*
+        * If the DFP_D/UFP_D sends a change in HPD when first notifying the
+        * DisplayPort driver that it is connected, then we wait until
+        * configuration is complete to signal HPD.
+        */
+       if (dp->pending_hpd) {
+               drm_connector_oob_hotplug_event(dp->connector_fwnode);
+               sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
+               dp->pending_hpd = false;
+       }
 
        return dp_altmode_notify(dp);
 }
index 784b9d8107e9bb770c18e5ee48531dd665dfaf9c..65da61150ba78415111dd11e6a9290205abebf16 100644 (file)
@@ -29,6 +29,7 @@ config TYPEC_MUX_INTEL_PMC
        tristate "Intel PMC mux control"
        depends on ACPI
        depends on INTEL_SCU_IPC
+       select USB_COMMON
        select USB_ROLE_SWITCH
        help
          Driver for USB muxes controlled by Intel PMC FW. Intel PMC FW can
index 80e580d50129128343ddf91ea32f206136706740..4d1122d9501326ddca933c919197ac02f464420e 100644 (file)
@@ -463,16 +463,18 @@ static int nb7vpq904m_probe(struct i2c_client *client)
 
        ret = nb7vpq904m_register_bridge(nb7);
        if (ret)
-               return ret;
+               goto err_disable_gpio;
 
        sw_desc.drvdata = nb7;
        sw_desc.fwnode = dev->fwnode;
        sw_desc.set = nb7vpq904m_sw_set;
 
        nb7->sw = typec_switch_register(dev, &sw_desc);
-       if (IS_ERR(nb7->sw))
-               return dev_err_probe(dev, PTR_ERR(nb7->sw),
-                                    "Error registering typec switch\n");
+       if (IS_ERR(nb7->sw)) {
+               ret = dev_err_probe(dev, PTR_ERR(nb7->sw),
+                                   "Error registering typec switch\n");
+               goto err_disable_gpio;
+       }
 
        retimer_desc.drvdata = nb7;
        retimer_desc.fwnode = dev->fwnode;
@@ -480,12 +482,21 @@ static int nb7vpq904m_probe(struct i2c_client *client)
 
        nb7->retimer = typec_retimer_register(dev, &retimer_desc);
        if (IS_ERR(nb7->retimer)) {
-               typec_switch_unregister(nb7->sw);
-               return dev_err_probe(dev, PTR_ERR(nb7->retimer),
-                                    "Error registering typec retimer\n");
+               ret = dev_err_probe(dev, PTR_ERR(nb7->retimer),
+                                   "Error registering typec retimer\n");
+               goto err_switch_unregister;
        }
 
        return 0;
+
+err_switch_unregister:
+       typec_switch_unregister(nb7->sw);
+
+err_disable_gpio:
+       gpiod_set_value(nb7->enable_gpio, 0);
+       regulator_disable(nb7->vcc_supply);
+
+       return ret;
 }
 
 static void nb7vpq904m_remove(struct i2c_client *client)
index 829d75ebab422b7756f232e9cb9d0c5689cdc89e..cc1d83926497723d82ca1f35cc31ad8f1143574a 100644 (file)
@@ -5349,6 +5349,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
                /* Do nothing, vbus drop expected */
                break;
 
+       case SNK_HARD_RESET_WAIT_VBUS:
+               /* Do nothing, its OK to receive vbus off events */
+               break;
+
        default:
                if (port->pwr_role == TYPEC_SINK && port->attached)
                        tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port));
@@ -5395,6 +5399,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
        case SNK_DEBOUNCED:
                /*Do nothing, still waiting for VSAFE5V for connect */
                break;
+       case SNK_HARD_RESET_WAIT_VBUS:
+               /* Do nothing, its OK to receive vbus off events */
+               break;
        default:
                if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
                        tcpm_set_state(port, SNK_UNATTACHED, 0);
index 25fc4120b618de16483ae2bd89af9bb866206bcd..b53420e874acb331d4a9f9bc2bcb2bfb60312fd2 100644 (file)
@@ -31,6 +31,7 @@ struct mlx5_vdpa_mr {
        struct list_head head;
        unsigned long num_directs;
        unsigned long num_klms;
+       /* state of dvq mr */
        bool initialized;
 
        /* serialize mkey creation and destruction */
@@ -121,6 +122,7 @@ int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *io
 int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb,
                        unsigned int asid);
 void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev);
+void mlx5_vdpa_destroy_mr_asid(struct mlx5_vdpa_dev *mvdev, unsigned int asid);
 
 #define mlx5_vdpa_warn(__dev, format, ...)                                                         \
        dev_warn((__dev)->mdev->device, "%s:%d:(pid %d) warning: " format, __func__, __LINE__,     \
index 03e5432297912a8da178f9f798c29fb2f6fb66db..5a1971fcd87b109d33be10ae8bdb678428e5d2d8 100644 (file)
@@ -489,60 +489,103 @@ static void destroy_user_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr
        }
 }
 
-void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev)
+static void _mlx5_vdpa_destroy_cvq_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid)
+{
+       if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid)
+               return;
+
+       prune_iotlb(mvdev);
+}
+
+static void _mlx5_vdpa_destroy_dvq_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid)
 {
        struct mlx5_vdpa_mr *mr = &mvdev->mr;
 
-       mutex_lock(&mr->mkey_mtx);
+       if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] != asid)
+               return;
+
        if (!mr->initialized)
-               goto out;
+               return;
 
-       prune_iotlb(mvdev);
        if (mr->user_mr)
                destroy_user_mr(mvdev, mr);
        else
                destroy_dma_mr(mvdev, mr);
 
        mr->initialized = false;
-out:
+}
+
+void mlx5_vdpa_destroy_mr_asid(struct mlx5_vdpa_dev *mvdev, unsigned int asid)
+{
+       struct mlx5_vdpa_mr *mr = &mvdev->mr;
+
+       mutex_lock(&mr->mkey_mtx);
+
+       _mlx5_vdpa_destroy_dvq_mr(mvdev, asid);
+       _mlx5_vdpa_destroy_cvq_mr(mvdev, asid);
+
        mutex_unlock(&mr->mkey_mtx);
 }
 
-static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
-                               struct vhost_iotlb *iotlb, unsigned int asid)
+void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev)
+{
+       mlx5_vdpa_destroy_mr_asid(mvdev, mvdev->group2asid[MLX5_VDPA_CVQ_GROUP]);
+       mlx5_vdpa_destroy_mr_asid(mvdev, mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]);
+}
+
+static int _mlx5_vdpa_create_cvq_mr(struct mlx5_vdpa_dev *mvdev,
+                                   struct vhost_iotlb *iotlb,
+                                   unsigned int asid)
+{
+       if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid)
+               return 0;
+
+       return dup_iotlb(mvdev, iotlb);
+}
+
+static int _mlx5_vdpa_create_dvq_mr(struct mlx5_vdpa_dev *mvdev,
+                                   struct vhost_iotlb *iotlb,
+                                   unsigned int asid)
 {
        struct mlx5_vdpa_mr *mr = &mvdev->mr;
        int err;
 
-       if (mr->initialized)
+       if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] != asid)
                return 0;
 
-       if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] == asid) {
-               if (iotlb)
-                       err = create_user_mr(mvdev, iotlb);
-               else
-                       err = create_dma_mr(mvdev, mr);
+       if (mr->initialized)
+               return 0;
 
-               if (err)
-                       return err;
-       }
+       if (iotlb)
+               err = create_user_mr(mvdev, iotlb);
+       else
+               err = create_dma_mr(mvdev, mr);
 
-       if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] == asid) {
-               err = dup_iotlb(mvdev, iotlb);
-               if (err)
-                       goto out_err;
-       }
+       if (err)
+               return err;
 
        mr->initialized = true;
+
+       return 0;
+}
+
+static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
+                               struct vhost_iotlb *iotlb, unsigned int asid)
+{
+       int err;
+
+       err = _mlx5_vdpa_create_dvq_mr(mvdev, iotlb, asid);
+       if (err)
+               return err;
+
+       err = _mlx5_vdpa_create_cvq_mr(mvdev, iotlb, asid);
+       if (err)
+               goto out_err;
+
        return 0;
 
 out_err:
-       if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] == asid) {
-               if (iotlb)
-                       destroy_user_mr(mvdev, mr);
-               else
-                       destroy_dma_mr(mvdev, mr);
-       }
+       _mlx5_vdpa_destroy_dvq_mr(mvdev, asid);
 
        return err;
 }
index 9138ef2fb2c853270ec11284a0824e84200276d3..37be945a0230884be614ea557cf2db921f2ed6d0 100644 (file)
@@ -2517,7 +2517,15 @@ static int mlx5_vdpa_set_driver_features(struct vdpa_device *vdev, u64 features)
        else
                ndev->rqt_size = 1;
 
-       ndev->cur_num_vqs = 2 * ndev->rqt_size;
+       /* Device must start with 1 queue pair, as per VIRTIO v1.2 spec, section
+        * 5.1.6.5.5 "Device operation in multiqueue mode":
+        *
+        * Multiqueue is disabled by default.
+        * The driver enables multiqueue by sending a command using class
+        * VIRTIO_NET_CTRL_MQ. The command selects the mode of multiqueue
+        * operation, as follows: ...
+        */
+       ndev->cur_num_vqs = 2;
 
        update_cvq_info(mvdev);
        return err;
@@ -2636,7 +2644,7 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev,
                goto err_mr;
 
        teardown_driver(ndev);
-       mlx5_vdpa_destroy_mr(mvdev);
+       mlx5_vdpa_destroy_mr_asid(mvdev, asid);
        err = mlx5_vdpa_create_mr(mvdev, iotlb, asid);
        if (err)
                goto err_mr;
@@ -2652,7 +2660,7 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev,
        return 0;
 
 err_setup:
-       mlx5_vdpa_destroy_mr(mvdev);
+       mlx5_vdpa_destroy_mr_asid(mvdev, asid);
 err_mr:
        return err;
 }
@@ -3548,17 +3556,6 @@ static void mlx5v_remove(struct auxiliary_device *adev)
        kfree(mgtdev);
 }
 
-static void mlx5v_shutdown(struct auxiliary_device *auxdev)
-{
-       struct mlx5_vdpa_mgmtdev *mgtdev;
-       struct mlx5_vdpa_net *ndev;
-
-       mgtdev = auxiliary_get_drvdata(auxdev);
-       ndev = mgtdev->ndev;
-
-       free_irqs(ndev);
-}
-
 static const struct auxiliary_device_id mlx5v_id_table[] = {
        { .name = MLX5_ADEV_NAME ".vnet", },
        {},
@@ -3570,7 +3567,6 @@ static struct auxiliary_driver mlx5v_driver = {
        .name = "vnet",
        .probe = mlx5v_probe,
        .remove = mlx5v_remove,
-       .shutdown = mlx5v_shutdown,
        .id_table = mlx5v_id_table,
 };
 
index 2e22418e3ab3058d0974dbf99aea59a3ef217560..c2d314d4614d3a8e84708fa9d6b47c53024ce229 100644 (file)
@@ -5,6 +5,5 @@ obj-$(CONFIG_PDS_VDPA) := pds_vdpa.o
 
 pds_vdpa-y := aux_drv.o \
              cmds.o \
+             debugfs.o \
              vdpa_dev.o
-
-pds_vdpa-$(CONFIG_DEBUG_FS) += debugfs.o
index 21a0dc0cb607ca5768dab0bf982dbee1cab8b863..9b04aad6ec35d7499da38d1209fb53a1cdae91a9 100644 (file)
@@ -176,6 +176,7 @@ static int identity_show(struct seq_file *seq, void *v)
 {
        struct pds_vdpa_aux *vdpa_aux = seq->private;
        struct vdpa_mgmt_dev *mgmt;
+       u64 hw_features;
 
        seq_printf(seq, "aux_dev:            %s\n",
                   dev_name(&vdpa_aux->padev->aux_dev.dev));
@@ -183,8 +184,9 @@ static int identity_show(struct seq_file *seq, void *v)
        mgmt = &vdpa_aux->vdpa_mdev;
        seq_printf(seq, "max_vqs:            %d\n", mgmt->max_supported_vqs);
        seq_printf(seq, "config_attr_mask:   %#llx\n", mgmt->config_attr_mask);
-       seq_printf(seq, "supported_features: %#llx\n", mgmt->supported_features);
-       print_feature_bits_all(seq, mgmt->supported_features);
+       hw_features = le64_to_cpu(vdpa_aux->ident.hw_features);
+       seq_printf(seq, "hw_features:        %#llx\n", hw_features);
+       print_feature_bits_all(seq, hw_features);
 
        return 0;
 }
@@ -200,7 +202,6 @@ static int config_show(struct seq_file *seq, void *v)
 {
        struct pds_vdpa_device *pdsv = seq->private;
        struct virtio_net_config vc;
-       u64 driver_features;
        u8 status;
 
        memcpy_fromio(&vc, pdsv->vdpa_aux->vd_mdev.device,
@@ -223,12 +224,8 @@ static int config_show(struct seq_file *seq, void *v)
        status = vp_modern_get_status(&pdsv->vdpa_aux->vd_mdev);
        seq_printf(seq, "dev_status:           %#x\n", status);
        print_status_bits(seq, status);
-
-       seq_printf(seq, "req_features:         %#llx\n", pdsv->req_features);
-       print_feature_bits_all(seq, pdsv->req_features);
-       driver_features = vp_modern_get_driver_features(&pdsv->vdpa_aux->vd_mdev);
-       seq_printf(seq, "driver_features:      %#llx\n", driver_features);
-       print_feature_bits_all(seq, driver_features);
+       seq_printf(seq, "negotiated_features:  %#llx\n", pdsv->negotiated_features);
+       print_feature_bits_all(seq, pdsv->negotiated_features);
        seq_printf(seq, "vdpa_index:           %d\n", pdsv->vdpa_index);
        seq_printf(seq, "num_vqs:              %d\n", pdsv->num_vqs);
 
index 5071a4d58f8db37f6d619d2f2d42f44d7f5188d6..52b2449182ad71976cc68cb58aa8b52a77ff5cea 100644 (file)
@@ -126,11 +126,9 @@ static void pds_vdpa_release_irq(struct pds_vdpa_device *pdsv, int qid)
 static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool ready)
 {
        struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
-       struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
        struct device *dev = &pdsv->vdpa_dev.dev;
        u64 driver_features;
        u16 invert_idx = 0;
-       int irq;
        int err;
 
        dev_dbg(dev, "%s: qid %d ready %d => %d\n",
@@ -143,19 +141,6 @@ static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool re
                invert_idx = PDS_VDPA_PACKED_INVERT_IDX;
 
        if (ready) {
-               irq = pci_irq_vector(pdev, qid);
-               snprintf(pdsv->vqs[qid].irq_name, sizeof(pdsv->vqs[qid].irq_name),
-                        "vdpa-%s-%d", dev_name(dev), qid);
-
-               err = request_irq(irq, pds_vdpa_isr, 0,
-                                 pdsv->vqs[qid].irq_name, &pdsv->vqs[qid]);
-               if (err) {
-                       dev_err(dev, "%s: no irq for qid %d: %pe\n",
-                               __func__, qid, ERR_PTR(err));
-                       return;
-               }
-               pdsv->vqs[qid].irq = irq;
-
                /* Pass vq setup info to DSC using adminq to gather up and
                 * send all info at once so FW can do its full set up in
                 * one easy operation
@@ -164,7 +149,6 @@ static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool re
                if (err) {
                        dev_err(dev, "Failed to init vq %d: %pe\n",
                                qid, ERR_PTR(err));
-                       pds_vdpa_release_irq(pdsv, qid);
                        ready = false;
                }
        } else {
@@ -172,7 +156,6 @@ static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool re
                if (err)
                        dev_err(dev, "%s: reset_vq failed qid %d: %pe\n",
                                __func__, qid, ERR_PTR(err));
-               pds_vdpa_release_irq(pdsv, qid);
        }
 
        pdsv->vqs[qid].ready = ready;
@@ -318,6 +301,7 @@ static int pds_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 featur
        struct device *dev = &pdsv->vdpa_dev.dev;
        u64 driver_features;
        u64 nego_features;
+       u64 hw_features;
        u64 missing;
 
        if (!(features & BIT_ULL(VIRTIO_F_ACCESS_PLATFORM)) && features) {
@@ -325,21 +309,26 @@ static int pds_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 featur
                return -EOPNOTSUPP;
        }
 
-       pdsv->req_features = features;
-
        /* Check for valid feature bits */
-       nego_features = features & le64_to_cpu(pdsv->vdpa_aux->ident.hw_features);
-       missing = pdsv->req_features & ~nego_features;
+       nego_features = features & pdsv->supported_features;
+       missing = features & ~nego_features;
        if (missing) {
                dev_err(dev, "Can't support all requested features in %#llx, missing %#llx features\n",
-                       pdsv->req_features, missing);
+                       features, missing);
                return -EOPNOTSUPP;
        }
 
+       pdsv->negotiated_features = nego_features;
+
        driver_features = pds_vdpa_get_driver_features(vdpa_dev);
        dev_dbg(dev, "%s: %#llx => %#llx\n",
                __func__, driver_features, nego_features);
 
+       /* if we're faking the F_MAC, strip it before writing to device */
+       hw_features = le64_to_cpu(pdsv->vdpa_aux->ident.hw_features);
+       if (!(hw_features & BIT_ULL(VIRTIO_NET_F_MAC)))
+               nego_features &= ~BIT_ULL(VIRTIO_NET_F_MAC);
+
        if (driver_features == nego_features)
                return 0;
 
@@ -352,7 +341,7 @@ static u64 pds_vdpa_get_driver_features(struct vdpa_device *vdpa_dev)
 {
        struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
 
-       return vp_modern_get_driver_features(&pdsv->vdpa_aux->vd_mdev);
+       return pdsv->negotiated_features;
 }
 
 static void pds_vdpa_set_config_cb(struct vdpa_device *vdpa_dev,
@@ -389,6 +378,72 @@ static u8 pds_vdpa_get_status(struct vdpa_device *vdpa_dev)
        return vp_modern_get_status(&pdsv->vdpa_aux->vd_mdev);
 }
 
+static int pds_vdpa_request_irqs(struct pds_vdpa_device *pdsv)
+{
+       struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
+       struct pds_vdpa_aux *vdpa_aux = pdsv->vdpa_aux;
+       struct device *dev = &pdsv->vdpa_dev.dev;
+       int max_vq, nintrs, qid, err;
+
+       max_vq = vdpa_aux->vdpa_mdev.max_supported_vqs;
+
+       nintrs = pci_alloc_irq_vectors(pdev, max_vq, max_vq, PCI_IRQ_MSIX);
+       if (nintrs < 0) {
+               dev_err(dev, "Couldn't get %d msix vectors: %pe\n",
+                       max_vq, ERR_PTR(nintrs));
+               return nintrs;
+       }
+
+       for (qid = 0; qid < pdsv->num_vqs; ++qid) {
+               int irq = pci_irq_vector(pdev, qid);
+
+               snprintf(pdsv->vqs[qid].irq_name, sizeof(pdsv->vqs[qid].irq_name),
+                        "vdpa-%s-%d", dev_name(dev), qid);
+
+               err = request_irq(irq, pds_vdpa_isr, 0,
+                                 pdsv->vqs[qid].irq_name,
+                                 &pdsv->vqs[qid]);
+               if (err) {
+                       dev_err(dev, "%s: no irq for qid %d: %pe\n",
+                               __func__, qid, ERR_PTR(err));
+                       goto err_release;
+               }
+
+               pdsv->vqs[qid].irq = irq;
+       }
+
+       vdpa_aux->nintrs = nintrs;
+
+       return 0;
+
+err_release:
+       while (qid--)
+               pds_vdpa_release_irq(pdsv, qid);
+
+       pci_free_irq_vectors(pdev);
+
+       vdpa_aux->nintrs = 0;
+
+       return err;
+}
+
+static void pds_vdpa_release_irqs(struct pds_vdpa_device *pdsv)
+{
+       struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
+       struct pds_vdpa_aux *vdpa_aux = pdsv->vdpa_aux;
+       int qid;
+
+       if (!vdpa_aux->nintrs)
+               return;
+
+       for (qid = 0; qid < pdsv->num_vqs; qid++)
+               pds_vdpa_release_irq(pdsv, qid);
+
+       pci_free_irq_vectors(pdev);
+
+       vdpa_aux->nintrs = 0;
+}
+
 static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
 {
        struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
@@ -399,6 +454,11 @@ static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
        old_status = pds_vdpa_get_status(vdpa_dev);
        dev_dbg(dev, "%s: old %#x new %#x\n", __func__, old_status, status);
 
+       if (status & ~old_status & VIRTIO_CONFIG_S_DRIVER_OK) {
+               if (pds_vdpa_request_irqs(pdsv))
+                       status = old_status | VIRTIO_CONFIG_S_FAILED;
+       }
+
        pds_vdpa_cmd_set_status(pdsv, status);
 
        /* Note: still working with FW on the need for this reset cmd */
@@ -409,6 +469,8 @@ static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
                        pdsv->vqs[i].avail_idx = 0;
                        pdsv->vqs[i].used_idx = 0;
                }
+
+               pds_vdpa_cmd_set_mac(pdsv, pdsv->mac);
        }
 
        if (status & ~old_status & VIRTIO_CONFIG_S_FEATURES_OK) {
@@ -418,6 +480,20 @@ static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
                                                        i, &pdsv->vqs[i].notify_pa);
                }
        }
+
+       if (old_status & ~status & VIRTIO_CONFIG_S_DRIVER_OK)
+               pds_vdpa_release_irqs(pdsv);
+}
+
+static void pds_vdpa_init_vqs_entry(struct pds_vdpa_device *pdsv, int qid,
+                                   void __iomem *notify)
+{
+       memset(&pdsv->vqs[qid], 0, sizeof(pdsv->vqs[0]));
+       pdsv->vqs[qid].qid = qid;
+       pdsv->vqs[qid].pdsv = pdsv;
+       pdsv->vqs[qid].ready = false;
+       pdsv->vqs[qid].irq = VIRTIO_MSI_NO_VECTOR;
+       pdsv->vqs[qid].notify = notify;
 }
 
 static int pds_vdpa_reset(struct vdpa_device *vdpa_dev)
@@ -441,14 +517,17 @@ static int pds_vdpa_reset(struct vdpa_device *vdpa_dev)
                        if (err)
                                dev_err(dev, "%s: reset_vq failed qid %d: %pe\n",
                                        __func__, i, ERR_PTR(err));
-                       pds_vdpa_release_irq(pdsv, i);
-                       memset(&pdsv->vqs[i], 0, sizeof(pdsv->vqs[0]));
-                       pdsv->vqs[i].ready = false;
                }
        }
 
        pds_vdpa_set_status(vdpa_dev, 0);
 
+       if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
+               /* Reset the vq info */
+               for (i = 0; i < pdsv->num_vqs && !err; i++)
+                       pds_vdpa_init_vqs_entry(pdsv, i, pdsv->vqs[i].notify);
+       }
+
        return 0;
 }
 
@@ -532,7 +611,6 @@ static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
        struct device *dma_dev;
        struct pci_dev *pdev;
        struct device *dev;
-       u8 mac[ETH_ALEN];
        int err;
        int i;
 
@@ -563,7 +641,7 @@ static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
 
        if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_FEATURES)) {
                u64 unsupp_features =
-                       add_config->device_features & ~mgmt->supported_features;
+                       add_config->device_features & ~pdsv->supported_features;
 
                if (unsupp_features) {
                        dev_err(dev, "Unsupported features: %#llx\n", unsupp_features);
@@ -614,29 +692,30 @@ static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
        }
 
        /* Set a mac, either from the user config if provided
-        * or set a random mac if default is 00:..:00
+        * or use the device's mac if not 00:..:00
+        * or set a random mac
         */
        if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR)) {
-               ether_addr_copy(mac, add_config->net.mac);
-               pds_vdpa_cmd_set_mac(pdsv, mac);
+               ether_addr_copy(pdsv->mac, add_config->net.mac);
        } else {
                struct virtio_net_config __iomem *vc;
 
                vc = pdsv->vdpa_aux->vd_mdev.device;
-               memcpy_fromio(mac, vc->mac, sizeof(mac));
-               if (is_zero_ether_addr(mac)) {
-                       eth_random_addr(mac);
-                       dev_info(dev, "setting random mac %pM\n", mac);
-                       pds_vdpa_cmd_set_mac(pdsv, mac);
+               memcpy_fromio(pdsv->mac, vc->mac, sizeof(pdsv->mac));
+               if (is_zero_ether_addr(pdsv->mac) &&
+                   (pdsv->supported_features & BIT_ULL(VIRTIO_NET_F_MAC))) {
+                       eth_random_addr(pdsv->mac);
+                       dev_info(dev, "setting random mac %pM\n", pdsv->mac);
                }
        }
+       pds_vdpa_cmd_set_mac(pdsv, pdsv->mac);
 
        for (i = 0; i < pdsv->num_vqs; i++) {
-               pdsv->vqs[i].qid = i;
-               pdsv->vqs[i].pdsv = pdsv;
-               pdsv->vqs[i].irq = VIRTIO_MSI_NO_VECTOR;
-               pdsv->vqs[i].notify = vp_modern_map_vq_notify(&pdsv->vdpa_aux->vd_mdev,
-                                                             i, &pdsv->vqs[i].notify_pa);
+               void __iomem *notify;
+
+               notify = vp_modern_map_vq_notify(&pdsv->vdpa_aux->vd_mdev,
+                                                i, &pdsv->vqs[i].notify_pa);
+               pds_vdpa_init_vqs_entry(pdsv, i, notify);
        }
 
        pdsv->vdpa_dev.mdev = &vdpa_aux->vdpa_mdev;
@@ -746,24 +825,19 @@ int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux)
 
        max_vqs = min_t(u16, dev_intrs, max_vqs);
        mgmt->max_supported_vqs = min_t(u16, PDS_VDPA_MAX_QUEUES, max_vqs);
-       vdpa_aux->nintrs = mgmt->max_supported_vqs;
+       vdpa_aux->nintrs = 0;
 
        mgmt->ops = &pds_vdpa_mgmt_dev_ops;
        mgmt->id_table = pds_vdpa_id_table;
        mgmt->device = dev;
        mgmt->supported_features = le64_to_cpu(vdpa_aux->ident.hw_features);
+
+       /* advertise F_MAC even if the device doesn't */
+       mgmt->supported_features |= BIT_ULL(VIRTIO_NET_F_MAC);
+
        mgmt->config_attr_mask = BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR);
        mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP);
        mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_FEATURES);
 
-       err = pci_alloc_irq_vectors(pdev, vdpa_aux->nintrs, vdpa_aux->nintrs,
-                                   PCI_IRQ_MSIX);
-       if (err < 0) {
-               dev_err(dev, "Couldn't get %d msix vectors: %pe\n",
-                       vdpa_aux->nintrs, ERR_PTR(err));
-               return err;
-       }
-       vdpa_aux->nintrs = err;
-
        return 0;
 }
index a1bc37de953746e1fc9250308bf81a701304e1fe..d984ba24a7dae13d928e4402139d9c906845e90a 100644 (file)
@@ -35,10 +35,11 @@ struct pds_vdpa_device {
        struct pds_vdpa_aux *vdpa_aux;
 
        struct pds_vdpa_vq_info vqs[PDS_VDPA_MAX_QUEUES];
-       u64 supported_features;         /* specified device features */
-       u64 req_features;               /* features requested by vdpa */
+       u64 supported_features;         /* supported device features */
+       u64 negotiated_features;        /* negotiated features */
        u8 vdpa_index;                  /* rsvd for future subdevice use */
        u8 num_vqs;                     /* num vqs in use */
+       u8 mac[ETH_ALEN];               /* mac selected when the device was added */
        struct vdpa_callback config_cb;
        struct notifier_block nb;
 };
index 965e32529eb856bd1452bcaabbabbba19aeb4bad..a7612e0783b36a89a61d5482a305c668a748ddac 100644 (file)
@@ -1247,44 +1247,41 @@ static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = {
        [VDPA_ATTR_MGMTDEV_DEV_NAME] = { .type = NLA_STRING },
        [VDPA_ATTR_DEV_NAME] = { .type = NLA_STRING },
        [VDPA_ATTR_DEV_NET_CFG_MACADDR] = NLA_POLICY_ETH_ADDR,
+       [VDPA_ATTR_DEV_NET_CFG_MAX_VQP] = { .type = NLA_U16 },
        /* virtio spec 1.1 section 5.1.4.1 for valid MTU range */
        [VDPA_ATTR_DEV_NET_CFG_MTU] = NLA_POLICY_MIN(NLA_U16, 68),
+       [VDPA_ATTR_DEV_QUEUE_INDEX] = { .type = NLA_U32 },
+       [VDPA_ATTR_DEV_FEATURES] = { .type = NLA_U64 },
 };
 
 static const struct genl_ops vdpa_nl_ops[] = {
        {
                .cmd = VDPA_CMD_MGMTDEV_GET,
-               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = vdpa_nl_cmd_mgmtdev_get_doit,
                .dumpit = vdpa_nl_cmd_mgmtdev_get_dumpit,
        },
        {
                .cmd = VDPA_CMD_DEV_NEW,
-               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = vdpa_nl_cmd_dev_add_set_doit,
                .flags = GENL_ADMIN_PERM,
        },
        {
                .cmd = VDPA_CMD_DEV_DEL,
-               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = vdpa_nl_cmd_dev_del_set_doit,
                .flags = GENL_ADMIN_PERM,
        },
        {
                .cmd = VDPA_CMD_DEV_GET,
-               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = vdpa_nl_cmd_dev_get_doit,
                .dumpit = vdpa_nl_cmd_dev_get_dumpit,
        },
        {
                .cmd = VDPA_CMD_DEV_CONFIG_GET,
-               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = vdpa_nl_cmd_dev_config_get_doit,
                .dumpit = vdpa_nl_cmd_dev_config_get_dumpit,
        },
        {
                .cmd = VDPA_CMD_DEV_VSTATS_GET,
-               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = vdpa_nl_cmd_dev_stats_get_doit,
                .flags = GENL_ADMIN_PERM,
        },
index dc38ed21319da92201b94708775507e0c7ce75be..df7869537ef146fdc62b6d29180e5e051c7c8d2c 100644 (file)
@@ -935,10 +935,10 @@ static void vduse_dev_irq_inject(struct work_struct *work)
 {
        struct vduse_dev *dev = container_of(work, struct vduse_dev, inject);
 
-       spin_lock_irq(&dev->irq_lock);
+       spin_lock_bh(&dev->irq_lock);
        if (dev->config_cb.callback)
                dev->config_cb.callback(dev->config_cb.private);
-       spin_unlock_irq(&dev->irq_lock);
+       spin_unlock_bh(&dev->irq_lock);
 }
 
 static void vduse_vq_irq_inject(struct work_struct *work)
@@ -946,10 +946,10 @@ static void vduse_vq_irq_inject(struct work_struct *work)
        struct vduse_virtqueue *vq = container_of(work,
                                        struct vduse_virtqueue, inject);
 
-       spin_lock_irq(&vq->irq_lock);
+       spin_lock_bh(&vq->irq_lock);
        if (vq->ready && vq->cb.callback)
                vq->cb.callback(vq->cb.private);
-       spin_unlock_irq(&vq->irq_lock);
+       spin_unlock_bh(&vq->irq_lock);
 }
 
 static bool vduse_vq_signal_irqfd(struct vduse_virtqueue *vq)
index c83f7f043470d687b32d92f6dfe864b1e93964c3..abef0619c7901af0f36232a558e46a1b1dbf16ae 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
 #include <linux/miscdevice.h>
+#include <linux/blk_types.h>
+#include <linux/bio.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi_common.h>
 #include <scsi/scsi_proto.h>
@@ -75,6 +77,9 @@ struct vhost_scsi_cmd {
        u32 tvc_prot_sgl_count;
        /* Saved unpacked SCSI LUN for vhost_scsi_target_queue_cmd() */
        u32 tvc_lun;
+       u32 copied_iov:1;
+       const void *saved_iter_addr;
+       struct iov_iter saved_iter;
        /* Pointer to the SGL formatted memory from virtio-scsi */
        struct scatterlist *tvc_sgl;
        struct scatterlist *tvc_prot_sgl;
@@ -328,8 +333,13 @@ static void vhost_scsi_release_cmd_res(struct se_cmd *se_cmd)
        int i;
 
        if (tv_cmd->tvc_sgl_count) {
-               for (i = 0; i < tv_cmd->tvc_sgl_count; i++)
-                       put_page(sg_page(&tv_cmd->tvc_sgl[i]));
+               for (i = 0; i < tv_cmd->tvc_sgl_count; i++) {
+                       if (tv_cmd->copied_iov)
+                               __free_page(sg_page(&tv_cmd->tvc_sgl[i]));
+                       else
+                               put_page(sg_page(&tv_cmd->tvc_sgl[i]));
+               }
+               kfree(tv_cmd->saved_iter_addr);
        }
        if (tv_cmd->tvc_prot_sgl_count) {
                for (i = 0; i < tv_cmd->tvc_prot_sgl_count; i++)
@@ -504,6 +514,28 @@ static void vhost_scsi_evt_work(struct vhost_work *work)
        mutex_unlock(&vq->mutex);
 }
 
+static int vhost_scsi_copy_sgl_to_iov(struct vhost_scsi_cmd *cmd)
+{
+       struct iov_iter *iter = &cmd->saved_iter;
+       struct scatterlist *sg = cmd->tvc_sgl;
+       struct page *page;
+       size_t len;
+       int i;
+
+       for (i = 0; i < cmd->tvc_sgl_count; i++) {
+               page = sg_page(&sg[i]);
+               len = sg[i].length;
+
+               if (copy_page_to_iter(page, 0, len, iter) != len) {
+                       pr_err("Could not copy data while handling misaligned cmd. Error %zu\n",
+                              len);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
 /* Fill in status and signal that we are done processing this command
  *
  * This is scheduled in the vhost work queue so we are called with the owner
@@ -527,15 +559,20 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
 
                pr_debug("%s tv_cmd %p resid %u status %#02x\n", __func__,
                        cmd, se_cmd->residual_count, se_cmd->scsi_status);
-
                memset(&v_rsp, 0, sizeof(v_rsp));
-               v_rsp.resid = cpu_to_vhost32(cmd->tvc_vq, se_cmd->residual_count);
-               /* TODO is status_qualifier field needed? */
-               v_rsp.status = se_cmd->scsi_status;
-               v_rsp.sense_len = cpu_to_vhost32(cmd->tvc_vq,
-                                                se_cmd->scsi_sense_length);
-               memcpy(v_rsp.sense, cmd->tvc_sense_buf,
-                      se_cmd->scsi_sense_length);
+
+               if (cmd->saved_iter_addr && vhost_scsi_copy_sgl_to_iov(cmd)) {
+                       v_rsp.response = VIRTIO_SCSI_S_BAD_TARGET;
+               } else {
+                       v_rsp.resid = cpu_to_vhost32(cmd->tvc_vq,
+                                                    se_cmd->residual_count);
+                       /* TODO is status_qualifier field needed? */
+                       v_rsp.status = se_cmd->scsi_status;
+                       v_rsp.sense_len = cpu_to_vhost32(cmd->tvc_vq,
+                                                        se_cmd->scsi_sense_length);
+                       memcpy(v_rsp.sense, cmd->tvc_sense_buf,
+                              se_cmd->scsi_sense_length);
+               }
 
                iov_iter_init(&iov_iter, ITER_DEST, cmd->tvc_resp_iov,
                              cmd->tvc_in_iovs, sizeof(v_rsp));
@@ -613,12 +650,12 @@ static int
 vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd,
                      struct iov_iter *iter,
                      struct scatterlist *sgl,
-                     bool write)
+                     bool is_prot)
 {
        struct page **pages = cmd->tvc_upages;
        struct scatterlist *sg = sgl;
-       ssize_t bytes;
-       size_t offset;
+       ssize_t bytes, mapped_bytes;
+       size_t offset, mapped_offset;
        unsigned int npages = 0;
 
        bytes = iov_iter_get_pages2(iter, pages, LONG_MAX,
@@ -627,13 +664,53 @@ vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd,
        if (bytes <= 0)
                return bytes < 0 ? bytes : -EFAULT;
 
+       mapped_bytes = bytes;
+       mapped_offset = offset;
+
        while (bytes) {
                unsigned n = min_t(unsigned, PAGE_SIZE - offset, bytes);
+               /*
+                * The block layer requires bios/requests to be a multiple of
+                * 512 bytes, but Windows can send us vecs that are misaligned.
+                * This can result in bios and later requests with misaligned
+                * sizes if we have to break up a cmd/scatterlist into multiple
+                * bios.
+                *
+                * We currently only break up a command into multiple bios if
+                * we hit the vec/seg limit, so check if our sgl_count is
+                * greater than the max and if a vec in the cmd has a
+                * misaligned offset/size.
+                */
+               if (!is_prot &&
+                   (offset & (SECTOR_SIZE - 1) || n & (SECTOR_SIZE - 1)) &&
+                   cmd->tvc_sgl_count > BIO_MAX_VECS) {
+                       WARN_ONCE(true,
+                                 "vhost-scsi detected misaligned IO. Performance may be degraded.");
+                       goto revert_iter_get_pages;
+               }
+
                sg_set_page(sg++, pages[npages++], n, offset);
                bytes -= n;
                offset = 0;
        }
+
        return npages;
+
+revert_iter_get_pages:
+       iov_iter_revert(iter, mapped_bytes);
+
+       npages = 0;
+       while (mapped_bytes) {
+               unsigned int n = min_t(unsigned int, PAGE_SIZE - mapped_offset,
+                                      mapped_bytes);
+
+               put_page(pages[npages++]);
+
+               mapped_bytes -= n;
+               mapped_offset = 0;
+       }
+
+       return -EINVAL;
 }
 
 static int
@@ -657,25 +734,80 @@ vhost_scsi_calc_sgls(struct iov_iter *iter, size_t bytes, int max_sgls)
 }
 
 static int
-vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write,
-                     struct iov_iter *iter,
-                     struct scatterlist *sg, int sg_count)
+vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
+                          struct scatterlist *sg, int sg_count)
+{
+       size_t len = iov_iter_count(iter);
+       unsigned int nbytes = 0;
+       struct page *page;
+       int i;
+
+       if (cmd->tvc_data_direction == DMA_FROM_DEVICE) {
+               cmd->saved_iter_addr = dup_iter(&cmd->saved_iter, iter,
+                                               GFP_KERNEL);
+               if (!cmd->saved_iter_addr)
+                       return -ENOMEM;
+       }
+
+       for (i = 0; i < sg_count; i++) {
+               page = alloc_page(GFP_KERNEL);
+               if (!page) {
+                       i--;
+                       goto err;
+               }
+
+               nbytes = min_t(unsigned int, PAGE_SIZE, len);
+               sg_set_page(&sg[i], page, nbytes, 0);
+
+               if (cmd->tvc_data_direction == DMA_TO_DEVICE &&
+                   copy_page_from_iter(page, 0, nbytes, iter) != nbytes)
+                       goto err;
+
+               len -= nbytes;
+       }
+
+       cmd->copied_iov = 1;
+       return 0;
+
+err:
+       pr_err("Could not read %u bytes while handling misaligned cmd\n",
+              nbytes);
+
+       for (; i >= 0; i--)
+               __free_page(sg_page(&sg[i]));
+       kfree(cmd->saved_iter_addr);
+       return -ENOMEM;
+}
+
+static int
+vhost_scsi_map_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
+                         struct scatterlist *sg, int sg_count, bool is_prot)
 {
        struct scatterlist *p = sg;
+       size_t revert_bytes;
        int ret;
 
        while (iov_iter_count(iter)) {
-               ret = vhost_scsi_map_to_sgl(cmd, iter, sg, write);
+               ret = vhost_scsi_map_to_sgl(cmd, iter, sg, is_prot);
                if (ret < 0) {
+                       revert_bytes = 0;
+
                        while (p < sg) {
-                               struct page *page = sg_page(p++);
-                               if (page)
+                               struct page *page = sg_page(p);
+
+                               if (page) {
                                        put_page(page);
+                                       revert_bytes += p->length;
+                               }
+                               p++;
                        }
+
+                       iov_iter_revert(iter, revert_bytes);
                        return ret;
                }
                sg += ret;
        }
+
        return 0;
 }
 
@@ -685,7 +817,6 @@ vhost_scsi_mapal(struct vhost_scsi_cmd *cmd,
                 size_t data_bytes, struct iov_iter *data_iter)
 {
        int sgl_count, ret;
-       bool write = (cmd->tvc_data_direction == DMA_FROM_DEVICE);
 
        if (prot_bytes) {
                sgl_count = vhost_scsi_calc_sgls(prot_iter, prot_bytes,
@@ -698,9 +829,9 @@ vhost_scsi_mapal(struct vhost_scsi_cmd *cmd,
                pr_debug("%s prot_sg %p prot_sgl_count %u\n", __func__,
                         cmd->tvc_prot_sgl, cmd->tvc_prot_sgl_count);
 
-               ret = vhost_scsi_iov_to_sgl(cmd, write, prot_iter,
-                                           cmd->tvc_prot_sgl,
-                                           cmd->tvc_prot_sgl_count);
+               ret = vhost_scsi_map_iov_to_sgl(cmd, prot_iter,
+                                               cmd->tvc_prot_sgl,
+                                               cmd->tvc_prot_sgl_count, true);
                if (ret < 0) {
                        cmd->tvc_prot_sgl_count = 0;
                        return ret;
@@ -716,8 +847,14 @@ vhost_scsi_mapal(struct vhost_scsi_cmd *cmd,
        pr_debug("%s data_sg %p data_sgl_count %u\n", __func__,
                  cmd->tvc_sgl, cmd->tvc_sgl_count);
 
-       ret = vhost_scsi_iov_to_sgl(cmd, write, data_iter,
-                                   cmd->tvc_sgl, cmd->tvc_sgl_count);
+       ret = vhost_scsi_map_iov_to_sgl(cmd, data_iter, cmd->tvc_sgl,
+                                       cmd->tvc_sgl_count, false);
+       if (ret == -EINVAL) {
+               sg_init_table(cmd->tvc_sgl, cmd->tvc_sgl_count);
+               ret = vhost_scsi_copy_iov_to_sgl(cmd, data_iter, cmd->tvc_sgl,
+                                                cmd->tvc_sgl_count);
+       }
+
        if (ret < 0) {
                cmd->tvc_sgl_count = 0;
                return ret;
index d88265dbebf4cb199934bd88878130e6a087338e..f216b2c702a1170878dae375c581cfd3e05bb3f9 100644 (file)
@@ -687,7 +687,7 @@ struct fb_var_cursorinfo {
        __u16 height;
        __u16 xspot;
        __u16 yspot;
-       __u8 data[1];                   /* field with [height][width]        */
+       DECLARE_FLEX_ARRAY(__u8, data); /* field with [height][width]        */
 };
 
 struct fb_cursorstate {
index 987c5f5f02414be9f9c7e24916e6d7ea27bd4f8a..f245da138e689818added8ca6e8410766972549b 100644 (file)
@@ -1308,7 +1308,7 @@ static struct platform_driver atmel_lcdfb_driver = {
        .resume         = atmel_lcdfb_resume,
        .driver         = {
                .name   = "atmel_lcdfb",
-               .of_match_table = of_match_ptr(atmel_lcdfb_dt_ids),
+               .of_match_table = atmel_lcdfb_dt_ids,
        },
 };
 
index 6fa2108fd912de0a4879094417d8b61febc6f2c1..e41c9fef4a3b6196ab8e923845f4adeca3ee2948 100644 (file)
@@ -203,8 +203,8 @@ static int goldfish_fb_probe(struct platform_device *pdev)
        }
 
        fb->irq = platform_get_irq(pdev, 0);
-       if (fb->irq <= 0) {
-               ret = -ENODEV;
+       if (fb->irq < 0) {
+               ret = fb->irq;
                goto err_no_irq;
        }
 
index 51fbf02a0343063d55c829cf27b9ad6e6f35ee21..76b50b6c98ad9af154801bf7c07d9e1891d7370d 100644 (file)
@@ -519,7 +519,9 @@ static int mmphw_probe(struct platform_device *pdev)
                              "unable to get clk %s\n", mi->clk_name);
                goto failed;
        }
-       clk_prepare_enable(ctrl->clk);
+       ret = clk_prepare_enable(ctrl->clk);
+       if (ret)
+               goto failed;
 
        /* init global regs */
        ctrl_set_default(ctrl);
index 11c3737982790cda958221c50ddfa18c7074453a..46881a6915498a4d2d1282c645f1e6e575009e8d 100644 (file)
@@ -399,8 +399,8 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
                /* Enable the PWM */
                pwm_enable(par->pwm);
 
-               dev_dbg(&par->client->dev, "Using PWM%d with a %lluns period.\n",
-                       par->pwm->pwm, pwm_get_period(par->pwm));
+               dev_dbg(&par->client->dev, "Using PWM %s with a %lluns period.\n",
+                       par->pwm->label, pwm_get_period(par->pwm));
        }
 
        /* Set initial contrast */
index 835f6cc2fb6644d445f005a1d74f77a17b4a8261..fa5226c198cc678775717d3d1db77c7090cfefd6 100644 (file)
@@ -38,11 +38,6 @@ module_param(bbm_block_size, ulong, 0444);
 MODULE_PARM_DESC(bbm_block_size,
                 "Big Block size in bytes. Default is 0 (auto-detection).");
 
-static bool bbm_safe_unplug = true;
-module_param(bbm_safe_unplug, bool, 0444);
-MODULE_PARM_DESC(bbm_safe_unplug,
-            "Use a safe unplug mechanism in BBM, avoiding long/endless loops");
-
 /*
  * virtio-mem currently supports the following modes of operation:
  *
@@ -173,6 +168,13 @@ struct virtio_mem {
                        /* The number of subblocks per Linux memory block. */
                        uint32_t sbs_per_mb;
 
+                       /*
+                        * Some of the Linux memory blocks tracked as "partially
+                        * plugged" are completely unplugged and can be offlined
+                        * and removed -- which previously failed.
+                        */
+                       bool have_unplugged_mb;
+
                        /* Summary of all memory block states. */
                        unsigned long mb_count[VIRTIO_MEM_SBM_MB_COUNT];
 
@@ -746,11 +748,15 @@ static int virtio_mem_offline_and_remove_memory(struct virtio_mem *vm,
                 * immediately instead of waiting.
                 */
                virtio_mem_retry(vm);
-       } else {
-               dev_dbg(&vm->vdev->dev,
-                       "offlining and removing memory failed: %d\n", rc);
+               return 0;
        }
-       return rc;
+       dev_dbg(&vm->vdev->dev, "offlining and removing memory failed: %d\n", rc);
+       /*
+        * We don't really expect this to fail, because we fake-offlined all
+        * memory already. But it could fail in corner cases.
+        */
+       WARN_ON_ONCE(rc != -ENOMEM && rc != -EBUSY);
+       return rc == -ENOMEM ? -ENOMEM : -EBUSY;
 }
 
 /*
@@ -766,6 +772,34 @@ static int virtio_mem_sbm_offline_and_remove_mb(struct virtio_mem *vm,
        return virtio_mem_offline_and_remove_memory(vm, addr, size);
 }
 
+/*
+ * Try (offlining and) removing memory from Linux in case all subblocks are
+ * unplugged. Can be called on online and offline memory blocks.
+ *
+ * May modify the state of memory blocks in virtio-mem.
+ */
+static int virtio_mem_sbm_try_remove_unplugged_mb(struct virtio_mem *vm,
+                                                 unsigned long mb_id)
+{
+       int rc;
+
+       /*
+        * Once all subblocks of a memory block were unplugged, offline and
+        * remove it.
+        */
+       if (!virtio_mem_sbm_test_sb_unplugged(vm, mb_id, 0, vm->sbm.sbs_per_mb))
+               return 0;
+
+       /* offline_and_remove_memory() works for online and offline memory. */
+       mutex_unlock(&vm->hotplug_mutex);
+       rc = virtio_mem_sbm_offline_and_remove_mb(vm, mb_id);
+       mutex_lock(&vm->hotplug_mutex);
+       if (!rc)
+               virtio_mem_sbm_set_mb_state(vm, mb_id,
+                                           VIRTIO_MEM_SBM_MB_UNUSED);
+       return rc;
+}
+
 /*
  * See virtio_mem_offline_and_remove_memory(): Try to offline and remove a
  * all Linux memory blocks covered by the big block.
@@ -1155,7 +1189,8 @@ static void virtio_mem_fake_online(unsigned long pfn, unsigned long nr_pages)
  * Try to allocate a range, marking pages fake-offline, effectively
  * fake-offlining them.
  */
-static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
+static int virtio_mem_fake_offline(struct virtio_mem *vm, unsigned long pfn,
+                                  unsigned long nr_pages)
 {
        const bool is_movable = is_zone_movable_page(pfn_to_page(pfn));
        int rc, retry_count;
@@ -1168,6 +1203,14 @@ static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
         * some guarantees.
         */
        for (retry_count = 0; retry_count < 5; retry_count++) {
+               /*
+                * If the config changed, stop immediately and go back to the
+                * main loop: avoid trying to keep unplugging if the device
+                * might have decided to not remove any more memory.
+                */
+               if (atomic_read(&vm->config_changed))
+                       return -EAGAIN;
+
                rc = alloc_contig_range(pfn, pfn + nr_pages, MIGRATE_MOVABLE,
                                        GFP_KERNEL);
                if (rc == -ENOMEM)
@@ -1917,7 +1960,7 @@ static int virtio_mem_sbm_unplug_sb_online(struct virtio_mem *vm,
        start_pfn = PFN_DOWN(virtio_mem_mb_id_to_phys(mb_id) +
                             sb_id * vm->sbm.sb_size);
 
-       rc = virtio_mem_fake_offline(start_pfn, nr_pages);
+       rc = virtio_mem_fake_offline(vm, start_pfn, nr_pages);
        if (rc)
                return rc;
 
@@ -1989,20 +2032,10 @@ static int virtio_mem_sbm_unplug_any_sb_online(struct virtio_mem *vm,
        }
 
 unplugged:
-       /*
-        * Once all subblocks of a memory block were unplugged, offline and
-        * remove it. This will usually not fail, as no memory is in use
-        * anymore - however some other notifiers might NACK the request.
-        */
-       if (virtio_mem_sbm_test_sb_unplugged(vm, mb_id, 0, vm->sbm.sbs_per_mb)) {
-               mutex_unlock(&vm->hotplug_mutex);
-               rc = virtio_mem_sbm_offline_and_remove_mb(vm, mb_id);
-               mutex_lock(&vm->hotplug_mutex);
-               if (!rc)
-                       virtio_mem_sbm_set_mb_state(vm, mb_id,
-                                                   VIRTIO_MEM_SBM_MB_UNUSED);
-       }
-
+       rc = virtio_mem_sbm_try_remove_unplugged_mb(vm, mb_id);
+       if (rc)
+               vm->sbm.have_unplugged_mb = 1;
+       /* Ignore errors, this is not critical. We'll retry later. */
        return 0;
 }
 
@@ -2111,38 +2144,32 @@ static int virtio_mem_bbm_offline_remove_and_unplug_bb(struct virtio_mem *vm,
                         VIRTIO_MEM_BBM_BB_ADDED))
                return -EINVAL;
 
-       if (bbm_safe_unplug) {
-               /*
-                * Start by fake-offlining all memory. Once we marked the device
-                * block as fake-offline, all newly onlined memory will
-                * automatically be kept fake-offline. Protect from concurrent
-                * onlining/offlining until we have a consistent state.
-                */
-               mutex_lock(&vm->hotplug_mutex);
-               virtio_mem_bbm_set_bb_state(vm, bb_id,
-                                           VIRTIO_MEM_BBM_BB_FAKE_OFFLINE);
+       /*
+        * Start by fake-offlining all memory. Once we marked the device
+        * block as fake-offline, all newly onlined memory will
+        * automatically be kept fake-offline. Protect from concurrent
+        * onlining/offlining until we have a consistent state.
+        */
+       mutex_lock(&vm->hotplug_mutex);
+       virtio_mem_bbm_set_bb_state(vm, bb_id, VIRTIO_MEM_BBM_BB_FAKE_OFFLINE);
 
-               for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
-                       page = pfn_to_online_page(pfn);
-                       if (!page)
-                               continue;
+       for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+               page = pfn_to_online_page(pfn);
+               if (!page)
+                       continue;
 
-                       rc = virtio_mem_fake_offline(pfn, PAGES_PER_SECTION);
-                       if (rc) {
-                               end_pfn = pfn;
-                               goto rollback_safe_unplug;
-                       }
+               rc = virtio_mem_fake_offline(vm, pfn, PAGES_PER_SECTION);
+               if (rc) {
+                       end_pfn = pfn;
+                       goto rollback;
                }
-               mutex_unlock(&vm->hotplug_mutex);
        }
+       mutex_unlock(&vm->hotplug_mutex);
 
        rc = virtio_mem_bbm_offline_and_remove_bb(vm, bb_id);
        if (rc) {
-               if (bbm_safe_unplug) {
-                       mutex_lock(&vm->hotplug_mutex);
-                       goto rollback_safe_unplug;
-               }
-               return rc;
+               mutex_lock(&vm->hotplug_mutex);
+               goto rollback;
        }
 
        rc = virtio_mem_bbm_unplug_bb(vm, bb_id);
@@ -2154,7 +2181,7 @@ static int virtio_mem_bbm_offline_remove_and_unplug_bb(struct virtio_mem *vm,
                                            VIRTIO_MEM_BBM_BB_UNUSED);
        return rc;
 
-rollback_safe_unplug:
+rollback:
        for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
                page = pfn_to_online_page(pfn);
                if (!page)
@@ -2260,12 +2287,13 @@ static int virtio_mem_unplug_request(struct virtio_mem *vm, uint64_t diff)
 
 /*
  * Try to unplug all blocks that couldn't be unplugged before, for example,
- * because the hypervisor was busy.
+ * because the hypervisor was busy. Further, offline and remove any memory
+ * blocks where we previously failed.
  */
-static int virtio_mem_unplug_pending_mb(struct virtio_mem *vm)
+static int virtio_mem_cleanup_pending_mb(struct virtio_mem *vm)
 {
        unsigned long id;
-       int rc;
+       int rc = 0;
 
        if (!vm->in_sbm) {
                virtio_mem_bbm_for_each_bb(vm, id,
@@ -2287,6 +2315,27 @@ static int virtio_mem_unplug_pending_mb(struct virtio_mem *vm)
                                            VIRTIO_MEM_SBM_MB_UNUSED);
        }
 
+       if (!vm->sbm.have_unplugged_mb)
+               return 0;
+
+       /*
+        * Let's retry (offlining and) removing completely unplugged Linux
+        * memory blocks.
+        */
+       vm->sbm.have_unplugged_mb = false;
+
+       mutex_lock(&vm->hotplug_mutex);
+       virtio_mem_sbm_for_each_mb(vm, id, VIRTIO_MEM_SBM_MB_MOVABLE_PARTIAL)
+               rc |= virtio_mem_sbm_try_remove_unplugged_mb(vm, id);
+       virtio_mem_sbm_for_each_mb(vm, id, VIRTIO_MEM_SBM_MB_KERNEL_PARTIAL)
+               rc |= virtio_mem_sbm_try_remove_unplugged_mb(vm, id);
+       virtio_mem_sbm_for_each_mb(vm, id, VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL)
+               rc |= virtio_mem_sbm_try_remove_unplugged_mb(vm, id);
+       mutex_unlock(&vm->hotplug_mutex);
+
+       if (rc)
+               vm->sbm.have_unplugged_mb = true;
+       /* Ignore errors, this is not critical. We'll retry later. */
        return 0;
 }
 
@@ -2368,9 +2417,9 @@ retry:
                virtio_mem_refresh_config(vm);
        }
 
-       /* Unplug any leftovers from previous runs */
+       /* Cleanup any leftovers from previous runs */
        if (!rc)
-               rc = virtio_mem_unplug_pending_mb(vm);
+               rc = virtio_mem_cleanup_pending_mb(vm);
 
        if (!rc && vm->requested_size != vm->plugged_size) {
                if (vm->requested_size > vm->plugged_size) {
@@ -2382,6 +2431,13 @@ retry:
                }
        }
 
+       /*
+        * Keep retrying to offline and remove completely unplugged Linux
+        * memory blocks.
+        */
+       if (!rc && vm->in_sbm && vm->sbm.have_unplugged_mb)
+               rc = -EBUSY;
+
        switch (rc) {
        case 0:
                vm->retry_timer_ms = VIRTIO_MEM_RETRY_TIMER_MIN_MS;
index a46a4a29e9295f7225bfbc631642e0e0a81f92d6..97760f611295941a36331573e53159ec5223eacc 100644 (file)
@@ -607,9 +607,8 @@ static void virtio_mmio_release_dev(struct device *_d)
        struct virtio_device *vdev =
                        container_of(_d, struct virtio_device, dev);
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
-       struct platform_device *pdev = vm_dev->pdev;
 
-       devm_kfree(&pdev->dev, vm_dev);
+       kfree(vm_dev);
 }
 
 /* Platform device */
@@ -620,7 +619,7 @@ static int virtio_mmio_probe(struct platform_device *pdev)
        unsigned long magic;
        int rc;
 
-       vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL);
+       vm_dev = kzalloc(sizeof(*vm_dev), GFP_KERNEL);
        if (!vm_dev)
                return -ENOMEM;
 
index a6c86f916dbdf5d87eb9dbaa277bfa60a6ea6a5b..c2524a7207cfaeed4149748c7890b3ce0f7e6ccd 100644 (file)
@@ -557,8 +557,6 @@ static int virtio_pci_probe(struct pci_dev *pci_dev,
 
        pci_set_master(pci_dev);
 
-       vp_dev->is_legacy = vp_dev->ldev.ioaddr ? true : false;
-
        rc = register_virtio_device(&vp_dev->vdev);
        reg_dev = vp_dev;
        if (rc)
index 2257f1b3d8ae1b5561b154955ce860d17c176944..d9cbb02b35a112e0940fa45999dd98261ba5e690 100644 (file)
@@ -223,6 +223,7 @@ int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev)
        vp_dev->config_vector = vp_config_vector;
        vp_dev->setup_vq = setup_vq;
        vp_dev->del_vq = del_vq;
+       vp_dev->is_legacy = true;
 
        return 0;
 }
index 989e2d7184ce463aeef8b4cd6df968f9d8839015..961161da59000d301deef6db6207e63a34df669a 100644 (file)
@@ -393,11 +393,13 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
        cb.callback = virtio_vdpa_config_cb;
        cb.private = vd_dev;
        ops->set_config_cb(vdpa, &cb);
+       kfree(masks);
 
        return 0;
 
 err_setup_vq:
        virtio_vdpa_del_vqs(vdev);
+       kfree(masks);
        return err;
 }
 
index 030ab44fce18d6c82760301c8358daad99441d72..82324c327a5027123e9d03c26a704276455db63b 100644 (file)
@@ -441,13 +441,23 @@ void btrfs_wait_block_group_cache_progress(struct btrfs_block_group *cache,
                                           u64 num_bytes)
 {
        struct btrfs_caching_control *caching_ctl;
+       int progress;
 
        caching_ctl = btrfs_get_caching_control(cache);
        if (!caching_ctl)
                return;
 
+       /*
+        * We've already failed to allocate from this block group, so even if
+        * there's enough space in the block group it isn't contiguous enough to
+        * allow for an allocation, so wait for at least the next wakeup tick,
+        * or for the thing to be done.
+        */
+       progress = atomic_read(&caching_ctl->progress);
+
        wait_event(caching_ctl->wait, btrfs_block_group_done(cache) ||
-                  (cache->free_space_ctl->free_space >= num_bytes));
+                  (progress != atomic_read(&caching_ctl->progress) &&
+                   (cache->free_space_ctl->free_space >= num_bytes)));
 
        btrfs_put_caching_control(caching_ctl);
 }
@@ -802,8 +812,10 @@ next:
 
                        if (total_found > CACHING_CTL_WAKE_UP) {
                                total_found = 0;
-                               if (wakeup)
+                               if (wakeup) {
+                                       atomic_inc(&caching_ctl->progress);
                                        wake_up(&caching_ctl->wait);
+                               }
                        }
                }
                path->slots[0]++;
@@ -910,6 +922,7 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait)
        init_waitqueue_head(&caching_ctl->wait);
        caching_ctl->block_group = cache;
        refcount_set(&caching_ctl->count, 2);
+       atomic_set(&caching_ctl->progress, 0);
        btrfs_init_work(&caching_ctl->work, caching_thread, NULL, NULL);
 
        spin_lock(&cache->lock);
index aba5dff66c19f1d2187be22423b193ff19d49c43..74b61e663028a866ee5fc3577f3f37fc8b245999 100644 (file)
@@ -90,6 +90,8 @@ struct btrfs_caching_control {
        wait_queue_head_t wait;
        struct btrfs_work work;
        struct btrfs_block_group *block_group;
+       /* Track progress of caching during allocation. */
+       atomic_t progress;
        refcount_t count;
 };
 
index f2d2b313bde5ab6c5b24229fa2cfda167b890b43..9419f4e37a58c3d20164d4f6bf9fb447792e45c2 100644 (file)
@@ -443,6 +443,7 @@ struct btrfs_drop_extents_args {
 
 struct btrfs_file_private {
        void *filldir_buf;
+       u64 last_index;
        struct extent_state *llseek_cached_state;
 };
 
index 6b457b010cbc4ae204bc211c521f389ad46ded4c..6d51db066503b87f48da7fc870dd78060cf2c981 100644 (file)
@@ -1632,6 +1632,7 @@ int btrfs_inode_delayed_dir_index_count(struct btrfs_inode *inode)
 }
 
 bool btrfs_readdir_get_delayed_items(struct inode *inode,
+                                    u64 last_index,
                                     struct list_head *ins_list,
                                     struct list_head *del_list)
 {
@@ -1651,14 +1652,14 @@ bool btrfs_readdir_get_delayed_items(struct inode *inode,
 
        mutex_lock(&delayed_node->mutex);
        item = __btrfs_first_delayed_insertion_item(delayed_node);
-       while (item) {
+       while (item && item->index <= last_index) {
                refcount_inc(&item->refs);
                list_add_tail(&item->readdir_list, ins_list);
                item = __btrfs_next_delayed_item(item);
        }
 
        item = __btrfs_first_delayed_deletion_item(delayed_node);
-       while (item) {
+       while (item && item->index <= last_index) {
                refcount_inc(&item->refs);
                list_add_tail(&item->readdir_list, del_list);
                item = __btrfs_next_delayed_item(item);
index 4f21daa3dbc7b306804d49a021e0fcae4f749b3e..dc1085b2a3976668e875d0dbf8b4d7aaf6b22dcd 100644 (file)
@@ -148,6 +148,7 @@ void btrfs_destroy_delayed_inodes(struct btrfs_fs_info *fs_info);
 
 /* Used for readdir() */
 bool btrfs_readdir_get_delayed_items(struct inode *inode,
+                                    u64 last_index,
                                     struct list_head *ins_list,
                                     struct list_head *del_list);
 void btrfs_readdir_put_delayed_items(struct inode *inode,
index 9b9914e5f03d0669101e84b99f02f4ce03c6d5e0..a9a2c5446c1804db8b9bbac82612615a41ce380b 100644 (file)
@@ -1103,7 +1103,8 @@ static int btrfs_init_fs_root(struct btrfs_root *root, dev_t anon_dev)
        btrfs_drew_lock_init(&root->snapshot_lock);
 
        if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID &&
-           !btrfs_is_data_reloc_root(root)) {
+           !btrfs_is_data_reloc_root(root) &&
+           is_fstree(root->root_key.objectid)) {
                set_bit(BTRFS_ROOT_SHAREABLE, &root->state);
                btrfs_check_and_init_root_item(&root->root_item);
        }
@@ -1300,6 +1301,16 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info,
        root = btrfs_get_global_root(fs_info, objectid);
        if (root)
                return root;
+
+       /*
+        * If we're called for non-subvolume trees, and above function didn't
+        * find one, do not try to read it from disk.
+        *
+        * This is namely for free-space-tree and quota tree, which can change
+        * at runtime and should only be grabbed from fs_info.
+        */
+       if (!is_fstree(objectid) && objectid != BTRFS_DATA_RELOC_TREE_OBJECTID)
+               return ERR_PTR(-ENOENT);
 again:
        root = btrfs_lookup_fs_root(fs_info, objectid);
        if (root) {
index 911908ea5f6f1f31fb0d9058b5c8a9add781a0a4..f396a9afa40322ffbb5f85f42c8750037b60dd5a 100644 (file)
@@ -4310,8 +4310,11 @@ have_block_group:
                        ret = 0;
                }
 
-               if (unlikely(block_group->cached == BTRFS_CACHE_ERROR))
+               if (unlikely(block_group->cached == BTRFS_CACHE_ERROR)) {
+                       if (!cache_block_group_error)
+                               cache_block_group_error = -EIO;
                        goto loop;
+               }
 
                if (!find_free_extent_check_size_class(ffe_ctl, block_group))
                        goto loop;
index a91d5ad2798428a803f749086912d169d9d544f0..90ad3006ef3a7f75ff54f94bf90af65b518cd026 100644 (file)
@@ -902,7 +902,30 @@ static void submit_extent_page(struct btrfs_bio_ctrl *bio_ctrl,
                size -= len;
                pg_offset += len;
                disk_bytenr += len;
-               bio_ctrl->len_to_oe_boundary -= len;
+
+               /*
+                * len_to_oe_boundary defaults to U32_MAX, which isn't page or
+                * sector aligned.  alloc_new_bio() then sets it to the end of
+                * our ordered extent for writes into zoned devices.
+                *
+                * When len_to_oe_boundary is tracking an ordered extent, we
+                * trust the ordered extent code to align things properly, and
+                * the check above to cap our write to the ordered extent
+                * boundary is correct.
+                *
+                * When len_to_oe_boundary is U32_MAX, the cap above would
+                * result in a 4095 byte IO for the last page right before
+                * we hit the bio limit of UINT_MAX.  bio_add_page() has all
+                * the checks required to make sure we don't overflow the bio,
+                * and we should just ignore len_to_oe_boundary completely
+                * unless we're using it to track an ordered extent.
+                *
+                * It's pretty hard to make a bio sized U32_MAX, but it can
+                * happen when the page cache is able to feed us contiguous
+                * pages for large extents.
+                */
+               if (bio_ctrl->len_to_oe_boundary != U32_MAX)
+                       bio_ctrl->len_to_oe_boundary -= len;
 
                /* Ordered extent boundary: move on to a new bio. */
                if (bio_ctrl->len_to_oe_boundary == 0)
@@ -2145,6 +2168,12 @@ retry:
                                continue;
                        }
 
+                       if (!folio_test_dirty(folio)) {
+                               /* Someone wrote it for us. */
+                               folio_unlock(folio);
+                               continue;
+                       }
+
                        if (wbc->sync_mode != WB_SYNC_NONE) {
                                if (folio_test_writeback(folio))
                                        submit_write_bio(bio_ctrl, 0);
@@ -2164,11 +2193,12 @@ retry:
                        }
 
                        /*
-                        * the filesystem may choose to bump up nr_to_write.
+                        * The filesystem may choose to bump up nr_to_write.
                         * We have to make sure to honor the new nr_to_write
-                        * at any time
+                        * at any time.
                         */
-                       nr_to_write_done = wbc->nr_to_write <= 0;
+                       nr_to_write_done = (wbc->sync_mode == WB_SYNC_NONE &&
+                                           wbc->nr_to_write <= 0);
                }
                folio_batch_release(&fbatch);
                cond_resched();
index 0cdb3e86f29b59a362c5eabcc2a37fc61da5607e..a6d8368ed0edd5784301ed40e5bed5e90ca6b60e 100644 (file)
@@ -760,8 +760,6 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
 
                if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) {
                        start = em_end;
-                       if (end != (u64)-1)
-                               len = start + len - em_end;
                        goto next;
                }
 
@@ -829,8 +827,8 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
                                if (!split)
                                        goto remove_em;
                        }
-                       split->start = start + len;
-                       split->len = em_end - (start + len);
+                       split->start = end;
+                       split->len = em_end - end;
                        split->block_start = em->block_start;
                        split->flags = flags;
                        split->compress_type = em->compress_type;
index 49cef61f6a39f50af1b3295a6c48b7f5de17c713..aa090b0b5d298c236a4a942d381a6e2efaab85cc 100644 (file)
@@ -1654,8 +1654,6 @@ out_unlock:
                                             clear_bits,
                                             page_ops);
                start += cur_alloc_size;
-               if (start >= end)
-                       return ret;
        }
 
        /*
@@ -1664,9 +1662,11 @@ out_unlock:
         * space_info's bytes_may_use counter, reserved in
         * btrfs_check_data_free_space().
         */
-       extent_clear_unlock_delalloc(inode, start, end, locked_page,
-                                    clear_bits | EXTENT_CLEAR_DATA_RESV,
-                                    page_ops);
+       if (start < end) {
+               clear_bits |= EXTENT_CLEAR_DATA_RESV;
+               extent_clear_unlock_delalloc(inode, start, end, locked_page,
+                                            clear_bits, page_ops);
+       }
        return ret;
 }
 
@@ -5872,6 +5872,74 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
        return d_splice_alias(inode, dentry);
 }
 
+/*
+ * Find the highest existing sequence number in a directory and then set the
+ * in-memory index_cnt variable to the first free sequence number.
+ */
+static int btrfs_set_inode_index_count(struct btrfs_inode *inode)
+{
+       struct btrfs_root *root = inode->root;
+       struct btrfs_key key, found_key;
+       struct btrfs_path *path;
+       struct extent_buffer *leaf;
+       int ret;
+
+       key.objectid = btrfs_ino(inode);
+       key.type = BTRFS_DIR_INDEX_KEY;
+       key.offset = (u64)-1;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+       if (ret < 0)
+               goto out;
+       /* FIXME: we should be able to handle this */
+       if (ret == 0)
+               goto out;
+       ret = 0;
+
+       if (path->slots[0] == 0) {
+               inode->index_cnt = BTRFS_DIR_START_INDEX;
+               goto out;
+       }
+
+       path->slots[0]--;
+
+       leaf = path->nodes[0];
+       btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
+
+       if (found_key.objectid != btrfs_ino(inode) ||
+           found_key.type != BTRFS_DIR_INDEX_KEY) {
+               inode->index_cnt = BTRFS_DIR_START_INDEX;
+               goto out;
+       }
+
+       inode->index_cnt = found_key.offset + 1;
+out:
+       btrfs_free_path(path);
+       return ret;
+}
+
+static int btrfs_get_dir_last_index(struct btrfs_inode *dir, u64 *index)
+{
+       if (dir->index_cnt == (u64)-1) {
+               int ret;
+
+               ret = btrfs_inode_delayed_dir_index_count(dir);
+               if (ret) {
+                       ret = btrfs_set_inode_index_count(dir);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       *index = dir->index_cnt;
+
+       return 0;
+}
+
 /*
  * All this infrastructure exists because dir_emit can fault, and we are holding
  * the tree lock when doing readdir.  For now just allocate a buffer and copy
@@ -5884,10 +5952,17 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
 static int btrfs_opendir(struct inode *inode, struct file *file)
 {
        struct btrfs_file_private *private;
+       u64 last_index;
+       int ret;
+
+       ret = btrfs_get_dir_last_index(BTRFS_I(inode), &last_index);
+       if (ret)
+               return ret;
 
        private = kzalloc(sizeof(struct btrfs_file_private), GFP_KERNEL);
        if (!private)
                return -ENOMEM;
+       private->last_index = last_index;
        private->filldir_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
        if (!private->filldir_buf) {
                kfree(private);
@@ -5954,7 +6029,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
 
        INIT_LIST_HEAD(&ins_list);
        INIT_LIST_HEAD(&del_list);
-       put = btrfs_readdir_get_delayed_items(inode, &ins_list, &del_list);
+       put = btrfs_readdir_get_delayed_items(inode, private->last_index,
+                                             &ins_list, &del_list);
 
 again:
        key.type = BTRFS_DIR_INDEX_KEY;
@@ -5972,6 +6048,8 @@ again:
                        break;
                if (found_key.offset < ctx->pos)
                        continue;
+               if (found_key.offset > private->last_index)
+                       break;
                if (btrfs_should_delete_dir_index(&del_list, found_key.offset))
                        continue;
                di = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
@@ -6107,57 +6185,6 @@ static int btrfs_update_time(struct inode *inode, struct timespec64 *now,
        return dirty ? btrfs_dirty_inode(BTRFS_I(inode)) : 0;
 }
 
-/*
- * find the highest existing sequence number in a directory
- * and then set the in-memory index_cnt variable to reflect
- * free sequence numbers
- */
-static int btrfs_set_inode_index_count(struct btrfs_inode *inode)
-{
-       struct btrfs_root *root = inode->root;
-       struct btrfs_key key, found_key;
-       struct btrfs_path *path;
-       struct extent_buffer *leaf;
-       int ret;
-
-       key.objectid = btrfs_ino(inode);
-       key.type = BTRFS_DIR_INDEX_KEY;
-       key.offset = (u64)-1;
-
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
-
-       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
-       if (ret < 0)
-               goto out;
-       /* FIXME: we should be able to handle this */
-       if (ret == 0)
-               goto out;
-       ret = 0;
-
-       if (path->slots[0] == 0) {
-               inode->index_cnt = BTRFS_DIR_START_INDEX;
-               goto out;
-       }
-
-       path->slots[0]--;
-
-       leaf = path->nodes[0];
-       btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
-
-       if (found_key.objectid != btrfs_ino(inode) ||
-           found_key.type != BTRFS_DIR_INDEX_KEY) {
-               inode->index_cnt = BTRFS_DIR_START_INDEX;
-               goto out;
-       }
-
-       inode->index_cnt = found_key.offset + 1;
-out:
-       btrfs_free_path(path);
-       return ret;
-}
-
 /*
  * helper to find a free sequence number in a given directory.  This current
  * code is very simple, later versions will do smarter things in the btree
index 25a3361caedc49353be2bc83bcc9ea28bfbd8e5c..46c3c1d5726686483bb4e15800546521f8c2f678 100644 (file)
@@ -1916,7 +1916,39 @@ again:
                                err = PTR_ERR(root);
                        break;
                }
-               ASSERT(root->reloc_root == reloc_root);
+
+               if (unlikely(root->reloc_root != reloc_root)) {
+                       if (root->reloc_root) {
+                               btrfs_err(fs_info,
+"reloc tree mismatch, root %lld has reloc root key (%lld %u %llu) gen %llu, expect reloc root key (%lld %u %llu) gen %llu",
+                                         root->root_key.objectid,
+                                         root->reloc_root->root_key.objectid,
+                                         root->reloc_root->root_key.type,
+                                         root->reloc_root->root_key.offset,
+                                         btrfs_root_generation(
+                                                 &root->reloc_root->root_item),
+                                         reloc_root->root_key.objectid,
+                                         reloc_root->root_key.type,
+                                         reloc_root->root_key.offset,
+                                         btrfs_root_generation(
+                                                 &reloc_root->root_item));
+                       } else {
+                               btrfs_err(fs_info,
+"reloc tree mismatch, root %lld has no reloc root, expect reloc root key (%lld %u %llu) gen %llu",
+                                         root->root_key.objectid,
+                                         reloc_root->root_key.objectid,
+                                         reloc_root->root_key.type,
+                                         reloc_root->root_key.offset,
+                                         btrfs_root_generation(
+                                                 &reloc_root->root_item));
+                       }
+                       list_add(&reloc_root->root_list, &reloc_roots);
+                       btrfs_put_root(root);
+                       btrfs_abort_transaction(trans, -EUCLEAN);
+                       if (!err)
+                               err = -EUCLEAN;
+                       break;
+               }
 
                /*
                 * set reference count to 1, so btrfs_recover_relocation
@@ -1989,7 +2021,7 @@ again:
                root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset,
                                         false);
                if (btrfs_root_refs(&reloc_root->root_item) > 0) {
-                       if (IS_ERR(root)) {
+                       if (WARN_ON(IS_ERR(root))) {
                                /*
                                 * For recovery we read the fs roots on mount,
                                 * and if we didn't find the root then we marked
@@ -1998,17 +2030,14 @@ again:
                                 * memory.  However there's no reason we can't
                                 * handle the error properly here just in case.
                                 */
-                               ASSERT(0);
                                ret = PTR_ERR(root);
                                goto out;
                        }
-                       if (root->reloc_root != reloc_root) {
+                       if (WARN_ON(root->reloc_root != reloc_root)) {
                                /*
-                                * This is actually impossible without something
-                                * going really wrong (like weird race condition
-                                * or cosmic rays).
+                                * This can happen if on-disk metadata has some
+                                * corruption, e.g. bad reloc tree key offset.
                                 */
-                               ASSERT(0);
                                ret = -EINVAL;
                                goto out;
                        }
index 4cae41bd6de0796a5d21af40ecc8135e7534ed75..7289f5bff397dce53710aabc8e0907634395c78b 100644 (file)
@@ -605,7 +605,8 @@ static void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr
                              btrfs_stack_header_bytenr(header), logical);
                return;
        }
-       if (memcmp(header->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE) != 0) {
+       if (memcmp(header->fsid, fs_info->fs_devices->metadata_uuid,
+                  BTRFS_FSID_SIZE) != 0) {
                bitmap_set(&stripe->meta_error_bitmap, sector_nr, sectors_per_tree);
                bitmap_set(&stripe->error_bitmap, sector_nr, sectors_per_tree);
                btrfs_warn_rl(fs_info,
index 038dfa8f1788238e0f9541d05e462b8019688d91..ab08a0b013112b28ba10bf55a35ef327df196b8a 100644 (file)
@@ -446,6 +446,20 @@ static int check_root_key(struct extent_buffer *leaf, struct btrfs_key *key,
        btrfs_item_key_to_cpu(leaf, &item_key, slot);
        is_root_item = (item_key.type == BTRFS_ROOT_ITEM_KEY);
 
+       /*
+        * Bad rootid for reloc trees.
+        *
+        * Reloc trees are only for subvolume trees, other trees only need
+        * to be COWed to be relocated.
+        */
+       if (unlikely(is_root_item && key->objectid == BTRFS_TREE_RELOC_OBJECTID &&
+                    !is_fstree(key->offset))) {
+               generic_err(leaf, slot,
+               "invalid reloc tree for root %lld, root id is not a subvolume tree",
+                           key->offset);
+               return -EUCLEAN;
+       }
+
        /* No such tree id */
        if (unlikely(key->objectid == 0)) {
                if (is_root_item)
index 2ecb76cf3d91f8c0941359ee0c4d6113e1a93a79..6aa9bf3661ac87b9f4f14446a44f4e4c26ac1fef 100644 (file)
@@ -4638,8 +4638,7 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info)
                }
        }
 
-       BUG_ON(fs_info->balance_ctl ||
-               test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags));
+       ASSERT(!test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags));
        atomic_dec(&fs_info->balance_cancel_req);
        mutex_unlock(&fs_info->balance_mutex);
        return 0;
index 4a2b39d9a61a2038fffa2b1a783d17f03be5c113..bdcffb04513fb537c561ad246f9fd5b6ae56494b 100644 (file)
@@ -2019,9 +2019,10 @@ unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn)
        }
 }
 
+WRAP_DIR_ITER(ceph_readdir) // FIXME!
 const struct file_operations ceph_dir_fops = {
        .read = ceph_read_dir,
-       .iterate = ceph_readdir,
+       .iterate_shared = shared_ceph_readdir,
        .llseek = ceph_dir_llseek,
        .open = ceph_open,
        .release = ceph_release,
@@ -2033,7 +2034,7 @@ const struct file_operations ceph_dir_fops = {
 };
 
 const struct file_operations ceph_snapdir_fops = {
-       .iterate = ceph_readdir,
+       .iterate_shared = shared_ceph_readdir,
        .llseek = ceph_dir_llseek,
        .open = ceph_open,
        .release = ceph_release,
index 66048a86c480ca9bd2075ea753cd013cf4593f1b..5fb367b1d4b066545ea36b9046a3c04fec4d314f 100644 (file)
@@ -4764,7 +4764,7 @@ static void delayed_work(struct work_struct *work)
 
        dout("mdsc delayed_work\n");
 
-       if (mdsc->stopping)
+       if (mdsc->stopping >= CEPH_MDSC_STOPPING_FLUSHED)
                return;
 
        mutex_lock(&mdsc->mutex);
@@ -4943,7 +4943,7 @@ void send_flush_mdlog(struct ceph_mds_session *s)
 void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)
 {
        dout("pre_umount\n");
-       mdsc->stopping = 1;
+       mdsc->stopping = CEPH_MDSC_STOPPING_BEGIN;
 
        ceph_mdsc_iterate_sessions(mdsc, send_flush_mdlog, true);
        ceph_mdsc_iterate_sessions(mdsc, lock_unlock_session, false);
index 724307ff89cd96e9e8f1e2ff0a61f714c315c357..86d2965e68a1fd1a52dde85f742b5733e62ec7c4 100644 (file)
@@ -380,6 +380,11 @@ struct cap_wait {
        int                     want;
 };
 
+enum {
+       CEPH_MDSC_STOPPING_BEGIN = 1,
+       CEPH_MDSC_STOPPING_FLUSHED = 2,
+};
+
 /*
  * mds client state
  */
index 3fc48b43cab0a2c5bccfe16445f09a9ecdd55761..a5f52013314d65d2c4ff576a01c08deffba872ae 100644 (file)
@@ -1374,6 +1374,16 @@ static void ceph_kill_sb(struct super_block *s)
        ceph_mdsc_pre_umount(fsc->mdsc);
        flush_fs_workqueues(fsc);
 
+       /*
+        * Though the kill_anon_super() will finally trigger the
+        * sync_filesystem() anyway, we still need to do it here
+        * and then bump the stage of shutdown to stop the work
+        * queue as earlier as possible.
+        */
+       sync_filesystem(s);
+
+       fsc->mdsc->stopping = CEPH_MDSC_STOPPING_FLUSHED;
+
        kill_anon_super(s);
 
        fsc->client->extra_mon_dispatch = NULL;
index 8450b1bd354b1b2cfa00817f91cc8d83578354c9..1b960de2bf3987667ea032da08efd34032687df0 100644 (file)
@@ -429,21 +429,14 @@ static int coda_readdir(struct file *coda_file, struct dir_context *ctx)
        cfi = coda_ftoc(coda_file);
        host_file = cfi->cfi_container;
 
-       if (host_file->f_op->iterate || host_file->f_op->iterate_shared) {
+       if (host_file->f_op->iterate_shared) {
                struct inode *host_inode = file_inode(host_file);
                ret = -ENOENT;
                if (!IS_DEADDIR(host_inode)) {
-                       if (host_file->f_op->iterate_shared) {
-                               inode_lock_shared(host_inode);
-                               ret = host_file->f_op->iterate_shared(host_file, ctx);
-                               file_accessed(host_file);
-                               inode_unlock_shared(host_inode);
-                       } else {
-                               inode_lock(host_inode);
-                               ret = host_file->f_op->iterate(host_file, ctx);
-                               file_accessed(host_file);
-                               inode_unlock(host_inode);
-                       }
+                       inode_lock_shared(host_inode);
+                       ret = host_file->f_op->iterate_shared(host_file, ctx);
+                       file_accessed(host_file);
+                       inode_unlock_shared(host_inode);
                }
                return ret;
        }
@@ -585,10 +578,11 @@ const struct inode_operations coda_dir_inode_operations = {
        .setattr        = coda_setattr,
 };
 
+WRAP_DIR_ITER(coda_readdir) // FIXME!
 const struct file_operations coda_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .iterate        = coda_readdir,
+       .iterate_shared = shared_coda_readdir,
        .open           = coda_open,
        .release        = coda_release,
        .fsync          = coda_fsync,
index 9d6a3c6158bdd1fa70666016f3e6b8f3d94100dd..566f68ddfa36e5154d50ba047b8cd303f235c31e 100644 (file)
@@ -889,8 +889,6 @@ static void erofs_kill_sb(struct super_block *sb)
 {
        struct erofs_sb_info *sbi;
 
-       WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC);
-
        /* pseudo mount for anon inodes */
        if (sb->s_flags & SB_KERNMOUNT) {
                kill_anon_super(sb);
index b69d89a11dd03bd78dc29d5d7e74767dee7e5bdd..de4f12152b62f15b5452329e12f1878e6dab0ed8 100644 (file)
@@ -1144,10 +1144,11 @@ static void z_erofs_do_decompressed_bvec(struct z_erofs_decompress_backend *be,
                                         struct z_erofs_bvec *bvec)
 {
        struct z_erofs_bvec_item *item;
+       unsigned int pgnr;
 
-       if (!((bvec->offset + be->pcl->pageofs_out) & ~PAGE_MASK)) {
-               unsigned int pgnr;
-
+       if (!((bvec->offset + be->pcl->pageofs_out) & ~PAGE_MASK) &&
+           (bvec->end == PAGE_SIZE ||
+            bvec->offset + bvec->end == be->pcl->length)) {
                pgnr = (bvec->offset + be->pcl->pageofs_out) >> PAGE_SHIFT;
                DBG_BUGON(pgnr >= be->nr_pages);
                if (!be->decompressed_pages[pgnr]) {
index 9f42f25fab9203de6b3fd0902342f000febad6b4..e918decb37358636113b9379860b75cf2af8e736 100644 (file)
@@ -69,7 +69,7 @@ static int exfat_allocate_bitmap(struct super_block *sb,
        }
        sbi->map_sectors = ((need_map_size - 1) >>
                        (sb->s_blocksize_bits)) + 1;
-       sbi->vol_amap = kmalloc_array(sbi->map_sectors,
+       sbi->vol_amap = kvmalloc_array(sbi->map_sectors,
                                sizeof(struct buffer_head *), GFP_KERNEL);
        if (!sbi->vol_amap)
                return -ENOMEM;
@@ -84,7 +84,7 @@ static int exfat_allocate_bitmap(struct super_block *sb,
                        while (j < i)
                                brelse(sbi->vol_amap[j++]);
 
-                       kfree(sbi->vol_amap);
+                       kvfree(sbi->vol_amap);
                        sbi->vol_amap = NULL;
                        return -EIO;
                }
@@ -138,7 +138,7 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi)
        for (i = 0; i < sbi->map_sectors; i++)
                __brelse(sbi->vol_amap[i]);
 
-       kfree(sbi->vol_amap);
+       kvfree(sbi->vol_amap);
 }
 
 int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync)
index 957574180a5e3e0e80b7830ecf8ec51b989a3e60..e1586bba6d86235ea5e372cea6a1fef3229cb9b1 100644 (file)
@@ -34,6 +34,7 @@ static int exfat_get_uniname_from_ext_entry(struct super_block *sb,
 {
        int i, err;
        struct exfat_entry_set_cache es;
+       unsigned int uni_len = 0, len;
 
        err = exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES);
        if (err)
@@ -52,7 +53,10 @@ static int exfat_get_uniname_from_ext_entry(struct super_block *sb,
                if (exfat_get_entry_type(ep) != TYPE_EXTEND)
                        break;
 
-               exfat_extract_uni_name(ep, uniname);
+               len = exfat_extract_uni_name(ep, uniname);
+               uni_len += len;
+               if (len != EXFAT_FILE_NAME_LEN || uni_len >= MAX_NAME_LENGTH)
+                       break;
                uniname += EXFAT_FILE_NAME_LEN;
        }
 
@@ -214,7 +218,10 @@ static void exfat_free_namebuf(struct exfat_dentry_namebuf *nb)
        exfat_init_namebuf(nb);
 }
 
-/* skip iterating emit_dots when dir is empty */
+/*
+ * Before calling dir_emit*(), sbi->s_lock should be released
+ * because page fault can occur in dir_emit*().
+ */
 #define ITER_POS_FILLED_DOTS    (2)
 static int exfat_iterate(struct file *file, struct dir_context *ctx)
 {
@@ -229,11 +236,10 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
        int err = 0, fake_offset = 0;
 
        exfat_init_namebuf(nb);
-       mutex_lock(&EXFAT_SB(sb)->s_lock);
 
        cpos = ctx->pos;
        if (!dir_emit_dots(file, ctx))
-               goto unlock;
+               goto out;
 
        if (ctx->pos == ITER_POS_FILLED_DOTS) {
                cpos = 0;
@@ -245,16 +251,18 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
        /* name buffer should be allocated before use */
        err = exfat_alloc_namebuf(nb);
        if (err)
-               goto unlock;
+               goto out;
 get_new:
+       mutex_lock(&EXFAT_SB(sb)->s_lock);
+
        if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode))
                goto end_of_dir;
 
        err = exfat_readdir(inode, &cpos, &de);
        if (err) {
                /*
-                * At least we tried to read a sector.  Move cpos to next sector
-                * position (should be aligned).
+                * At least we tried to read a sector.
+                * Move cpos to next sector position (should be aligned).
                 */
                if (err == -EIO) {
                        cpos += 1 << (sb->s_blocksize_bits);
@@ -277,16 +285,10 @@ get_new:
                inum = iunique(sb, EXFAT_ROOT_INO);
        }
 
-       /*
-        * Before calling dir_emit(), sb_lock should be released.
-        * Because page fault can occur in dir_emit() when the size
-        * of buffer given from user is larger than one page size.
-        */
        mutex_unlock(&EXFAT_SB(sb)->s_lock);
        if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum,
                        (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG))
-               goto out_unlocked;
-       mutex_lock(&EXFAT_SB(sb)->s_lock);
+               goto out;
        ctx->pos = cpos;
        goto get_new;
 
@@ -294,9 +296,8 @@ end_of_dir:
        if (!cpos && fake_offset)
                cpos = ITER_POS_FILLED_DOTS;
        ctx->pos = cpos;
-unlock:
        mutex_unlock(&EXFAT_SB(sb)->s_lock);
-out_unlocked:
+out:
        /*
         * To improve performance, free namebuf after unlock sb_lock.
         * If namebuf is not allocated, this function do nothing
@@ -305,10 +306,11 @@ out_unlocked:
        return err;
 }
 
+WRAP_DIR_ITER(exfat_iterate) // FIXME!
 const struct file_operations exfat_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .iterate        = exfat_iterate,
+       .iterate_shared = shared_exfat_iterate,
        .unlocked_ioctl = exfat_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl = exfat_compat_ioctl,
@@ -1079,7 +1081,8 @@ rewind:
                        if (entry_type == TYPE_EXTEND) {
                                unsigned short entry_uniname[16], unichar;
 
-                               if (step != DIRENT_STEP_NAME) {
+                               if (step != DIRENT_STEP_NAME ||
+                                   name_len >= MAX_NAME_LENGTH) {
                                        step = DIRENT_STEP_FILE;
                                        continue;
                                }
index 40e624cf7e929194bb4ef9ff2d17519652e6b663..d1dbe47c7975fc02ff65603089881a078673daea 100644 (file)
@@ -315,7 +315,7 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
                goto out;
 
        error = -EINVAL;
-       if (!file->f_op->iterate && !file->f_op->iterate_shared)
+       if (!file->f_op->iterate_shared)
                goto out_close;
 
        buffer.sequence = 0;
index 35c62b54c9d65c0bb3ccc74b2f5b31c2edec1eaf..3fd003a8604f854e03c24951c36be7a8d1f0e158 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -1036,12 +1036,28 @@ unsigned long __fdget_raw(unsigned int fd)
        return __fget_light(fd, 0);
 }
 
+/*
+ * Try to avoid f_pos locking. We only need it if the
+ * file is marked for FMODE_ATOMIC_POS, and it can be
+ * accessed multiple ways.
+ *
+ * Always do it for directories, because pidfd_getfd()
+ * can make a file accessible even if it otherwise would
+ * not be, and for directories this is a correctness
+ * issue, not a "POSIX requirement".
+ */
+static inline bool file_needs_f_pos_lock(struct file *file)
+{
+       return (file->f_mode & FMODE_ATOMIC_POS) &&
+               (file_count(file) > 1 || file->f_op->iterate_shared);
+}
+
 unsigned long __fdget_pos(unsigned int fd)
 {
        unsigned long v = __fdget(fd);
        struct file *file = (struct file *)(v & ~3);
 
-       if (file && (file->f_mode & FMODE_ATOMIC_POS)) {
+       if (file && file_needs_f_pos_lock(file)) {
                v |= FDPUT_POS_UNLOCK;
                mutex_lock(&file->f_pos_lock);
        }
index 1bf3c4453516f246fdbc2aae81befcfe11af3afc..b43fa8b8fc05a13a3917d6c568d99a71e4ff117b 100644 (file)
@@ -1578,7 +1578,7 @@ const struct file_operations gfs2_file_fops = {
        .fsync          = gfs2_fsync,
        .lock           = gfs2_lock,
        .flock          = gfs2_flock,
-       .splice_read    = filemap_splice_read,
+       .splice_read    = copy_splice_read,
        .splice_write   = gfs2_file_splice_write,
        .setlease       = simple_nosetlease,
        .fallocate      = gfs2_fallocate,
@@ -1609,7 +1609,7 @@ const struct file_operations gfs2_file_fops_nolock = {
        .open           = gfs2_open,
        .release        = gfs2_release,
        .fsync          = gfs2_fsync,
-       .splice_read    = filemap_splice_read,
+       .splice_read    = copy_splice_read,
        .splice_write   = gfs2_file_splice_write,
        .setlease       = generic_setlease,
        .fallocate      = gfs2_fallocate,
index ec1631257978a89fa930bef50340df7a1653f68f..7e835be7032d0bc751929ddaec8fc7a739168a16 100644 (file)
@@ -230,9 +230,11 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
 {
 
        struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+       struct super_block *sb = sdp->sd_vfs;
        struct gfs2_bufdata *bd;
        struct gfs2_meta_header *mh;
        struct gfs2_trans *tr = current->journal_info;
+       bool withdraw = false;
 
        lock_buffer(bh);
        if (buffer_pinned(bh)) {
@@ -266,13 +268,15 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
                       (unsigned long long)bd->bd_bh->b_blocknr);
                BUG();
        }
-       if (unlikely(test_bit(SDF_FROZEN, &sdp->sd_flags))) {
-               fs_info(sdp, "GFS2:adding buf while frozen\n");
-               gfs2_assert_withdraw(sdp, 0);
-       }
        if (unlikely(gfs2_withdrawn(sdp))) {
                fs_info(sdp, "GFS2:adding buf while withdrawn! 0x%llx\n",
                        (unsigned long long)bd->bd_bh->b_blocknr);
+               goto out_unlock;
+       }
+       if (unlikely(sb->s_writers.frozen == SB_FREEZE_COMPLETE)) {
+               fs_info(sdp, "GFS2:adding buf while frozen\n");
+               withdraw = true;
+               goto out_unlock;
        }
        gfs2_pin(sdp, bd->bd_bh);
        mh->__pad0 = cpu_to_be64(0);
@@ -281,6 +285,8 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
        tr->tr_num_buf_new++;
 out_unlock:
        gfs2_log_unlock(sdp);
+       if (withdraw)
+               gfs2_assert_withdraw(sdp, 0);
 out:
        unlock_buffer(bh);
 }
index 8fefb69e1f84a93dd10f7be2af07cb510c440086..67611a360031b2c24d0f1380cf6505e16eeabdb7 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/fsnotify.h>
 #include <linux/mount.h>
 #include <linux/posix_acl.h>
-#include <linux/prefetch.h>
 #include <linux/buffer_head.h> /* for inode_has_buffers */
 #include <linux/ratelimit.h>
 #include <linux/list_lru.h>
@@ -1041,8 +1040,6 @@ struct inode *new_inode(struct super_block *sb)
 {
        struct inode *inode;
 
-       spin_lock_prefetch(&sb->s_inode_list_lock);
-
        inode = new_inode_pseudo(sb);
        if (inode)
                inode_sb_list_add(inode);
index 9b030297aa64c8f9378097e05012d660a9348cb3..e98ddb2b1cf259c9e1beb99767e7c4cc22d0e239 100644 (file)
@@ -1535,9 +1535,10 @@ const struct inode_operations jfs_dir_inode_operations = {
 #endif
 };
 
+WRAP_DIR_ITER(jfs_readdir) // FIXME!
 const struct file_operations jfs_dir_operations = {
        .read           = generic_read_dir,
-       .iterate        = jfs_readdir,
+       .iterate_shared = shared_jfs_readdir,
        .fsync          = jfs_fsync,
        .unlocked_ioctl = jfs_ioctl,
        .compat_ioctl   = compat_ptr_ioctl,
index 9a18c5a69ace63f6b970b698a16a804cf4dc2745..aaffaaa336cc55d8bc6a17819485a82c58f9f1e4 100644 (file)
@@ -472,20 +472,26 @@ out:
        return result;
 }
 
-static void
-nfs_direct_join_group(struct list_head *list, struct inode *inode)
+static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
 {
-       struct nfs_page *req, *next;
+       struct nfs_page *req, *subreq;
 
        list_for_each_entry(req, list, wb_list) {
-               if (req->wb_head != req || req->wb_this_page == req)
+               if (req->wb_head != req)
                        continue;
-               for (next = req->wb_this_page;
-                               next != req->wb_head;
-                               next = next->wb_this_page) {
-                       nfs_list_remove_request(next);
-                       nfs_release_request(next);
-               }
+               subreq = req->wb_this_page;
+               if (subreq == req)
+                       continue;
+               do {
+                       /*
+                        * Remove subrequests from this list before freeing
+                        * them in the call to nfs_join_page_group().
+                        */
+                       if (!list_empty(&subreq->wb_list)) {
+                               nfs_list_remove_request(subreq);
+                               nfs_release_request(subreq);
+                       }
+               } while ((subreq = subreq->wb_this_page) != req);
                nfs_join_page_group(req, inode);
        }
 }
index 63802d19555665a62f3b44b2c6668986e4f34e81..49f78e23b34c0bf928de2f96a73894ec158e2482 100644 (file)
@@ -1377,7 +1377,6 @@ ssize_t nfs42_proc_getxattr(struct inode *inode, const char *name,
        for (i = 0; i < np; i++) {
                pages[i] = alloc_page(GFP_KERNEL);
                if (!pages[i]) {
-                       np = i + 1;
                        err = -ENOMEM;
                        goto out;
                }
@@ -1401,8 +1400,8 @@ ssize_t nfs42_proc_getxattr(struct inode *inode, const char *name,
        } while (exception.retry);
 
 out:
-       while (--np >= 0)
-               __free_page(pages[np]);
+       while (--i >= 0)
+               __free_page(pages[i]);
        kfree(pages);
 
        return err;
index e1a886b58354cf905018beb46beb89927dd6dbb3..832fa226b8f2689538549169f208779b6d69d1c6 100644 (file)
@@ -6004,9 +6004,8 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf,
 out_ok:
        ret = res.acl_len;
 out_free:
-       for (i = 0; i < npages; i++)
-               if (pages[i])
-                       __free_page(pages[i]);
+       while (--i >= 0)
+               __free_page(pages[i]);
        if (res.acl_scratch)
                __free_page(res.acl_scratch);
        kfree(pages);
@@ -7181,8 +7180,15 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
                } else if (!nfs4_update_lock_stateid(lsp, &data->res.stateid))
                        goto out_restart;
                break;
-       case -NFS4ERR_BAD_STATEID:
        case -NFS4ERR_OLD_STATEID:
+               if (data->arg.new_lock_owner != 0 &&
+                       nfs4_refresh_open_old_stateid(&data->arg.open_stateid,
+                                       lsp->ls_state))
+                       goto out_restart;
+               if (nfs4_refresh_lock_old_stateid(&data->arg.lock_stateid, lsp))
+                       goto out_restart;
+               fallthrough;
+       case -NFS4ERR_BAD_STATEID:
        case -NFS4ERR_STALE_STATEID:
        case -NFS4ERR_EXPIRED:
                if (data->arg.new_lock_owner != 0) {
index acda8f033d30d5f02e76749bc0a3522f19bae71e..bf378ecd5d9fdde62ac97587d2b0da505d6cbb83 100644 (file)
@@ -345,8 +345,10 @@ void nfs_sysfs_move_sb_to_server(struct nfs_server *server)
        int ret = -ENOMEM;
 
        s = kasprintf(GFP_KERNEL, "server-%d", server->s_sysfs_id);
-       if (s)
+       if (s) {
                ret = kobject_rename(&server->kobj, s);
+               kfree(s);
+       }
        if (ret < 0)
                pr_warn("NFS: rename sysfs %s failed (%d)\n",
                                        server->kobj.name, ret);
index 8a2321d191944c8c1195fa3bbe647912a70ebf89..2c9074ab2315a72b26239842e40882a86107c6ab 100644 (file)
@@ -956,10 +956,13 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
        last_page = page + (offset + sd->len - 1) / PAGE_SIZE;
        for (page += offset / PAGE_SIZE; page <= last_page; page++) {
                /*
-                * Skip page replacement when extending the contents
-                * of the current page.
+                * Skip page replacement when extending the contents of the
+                * current page.  But note that we may get two zero_pages in a
+                * row from shmem.
                 */
-               if (page == *(rqstp->rq_next_page - 1))
+               if (page == *(rqstp->rq_next_page - 1) &&
+                   offset_in_page(rqstp->rq_res.page_base +
+                                  rqstp->rq_res.page_len))
                        continue;
                if (unlikely(!svc_rqst_replace_page(rqstp, page)))
                        return -EIO;
index a8ce522ac747931575104447288cdbe2ed317d0f..35bc793053180c441ba41d8f40999415df0fc60f 100644 (file)
@@ -1101,9 +1101,17 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned int nr_dirty)
 
 int __nilfs_mark_inode_dirty(struct inode *inode, int flags)
 {
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
        struct buffer_head *ibh;
        int err;
 
+       /*
+        * Do not dirty inodes after the log writer has been detached
+        * and its nilfs_root struct has been freed.
+        */
+       if (unlikely(nilfs_purging(nilfs)))
+               return 0;
+
        err = nilfs_load_inode_block(inode, &ibh);
        if (unlikely(err)) {
                nilfs_warn(inode->i_sb,
index c2553024bd25e651c38f99c414816a4bc57b51a1..581691e4be49181b1497c594ee5ab4eabf88b2cb 100644 (file)
@@ -2845,6 +2845,7 @@ void nilfs_detach_log_writer(struct super_block *sb)
                nilfs_segctor_destroy(nilfs->ns_writer);
                nilfs->ns_writer = NULL;
        }
+       set_nilfs_purging(nilfs);
 
        /* Force to free the list of dirty files */
        spin_lock(&nilfs->ns_inode_lock);
@@ -2857,4 +2858,5 @@ void nilfs_detach_log_writer(struct super_block *sb)
        up_write(&nilfs->ns_segctor_sem);
 
        nilfs_dispose_list(nilfs, &garbage_list, 1);
+       clear_nilfs_purging(nilfs);
 }
index 47c7dfbb7ea584641d541cc8e10c6533b28d372c..cd4ae1b8ae165adeeaf532c13fae021d86c2bc05 100644 (file)
@@ -29,6 +29,7 @@ enum {
        THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */
        THE_NILFS_GC_RUNNING,   /* gc process is running */
        THE_NILFS_SB_DIRTY,     /* super block is dirty */
+       THE_NILFS_PURGING,      /* disposing dirty files for cleanup */
 };
 
 /**
@@ -208,6 +209,7 @@ THE_NILFS_FNS(INIT, init)
 THE_NILFS_FNS(DISCONTINUED, discontinued)
 THE_NILFS_FNS(GC_RUNNING, gc_running)
 THE_NILFS_FNS(SB_DIRTY, sb_dirty)
+THE_NILFS_FNS(PURGING, purging)
 
 /*
  * Mount option operations
index 518c3a21a556d1084a0c1bddb5a30b18b6db1516..4596c90e7b7cf096e0c9b590dfc4ef59eb3fe9b8 100644 (file)
@@ -1525,10 +1525,11 @@ static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
 
 #endif /* NTFS_RW */
 
+WRAP_DIR_ITER(ntfs_readdir) // FIXME!
 const struct file_operations ntfs_dir_ops = {
        .llseek         = generic_file_llseek,  /* Seek inside directory. */
        .read           = generic_read_dir,     /* Return -EISDIR. */
-       .iterate        = ntfs_readdir,         /* Read directory contents. */
+       .iterate_shared = shared_ntfs_readdir,  /* Read directory contents. */
 #ifdef NTFS_RW
        .fsync          = ntfs_dir_fsync,       /* Sync a directory to disk. */
 #endif /* NTFS_RW */
index 91a194596552e2a5eaf762113efc629513dc64d1..bf2c17ea96a060f3bfcb9917599a27ac3ac410d9 100644 (file)
@@ -2793,10 +2793,11 @@ const struct file_operations ocfs2_fops = {
        .remap_file_range = ocfs2_remap_file_range,
 };
 
+WRAP_DIR_ITER(ocfs2_readdir) // FIXME!
 const struct file_operations ocfs2_dops = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .iterate        = ocfs2_readdir,
+       .iterate_shared = shared_ocfs2_readdir,
        .fsync          = ocfs2_sync_file,
        .release        = ocfs2_dir_release,
        .open           = ocfs2_dir_open,
@@ -2842,7 +2843,7 @@ const struct file_operations ocfs2_fops_no_plocks = {
 const struct file_operations ocfs2_dops_no_plocks = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .iterate        = ocfs2_readdir,
+       .iterate_shared = shared_ocfs2_readdir,
        .fsync          = ocfs2_sync_file,
        .release        = ocfs2_dir_release,
        .open           = ocfs2_dir_open,
index 0c55c8e7f837d8ef03ab19b5645b40401205ee42..e6ead0f19964957afd601cb4f7ad1ab88a9a510c 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -1322,7 +1322,7 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
                lookup_flags |= LOOKUP_IN_ROOT;
        if (how->resolve & RESOLVE_CACHED) {
                /* Don't bother even trying for create/truncate/tmpfile open */
-               if (flags & (O_TRUNC | O_CREAT | O_TMPFILE))
+               if (flags & (O_TRUNC | O_CREAT | __O_TMPFILE))
                        return -EAGAIN;
                lookup_flags |= LOOKUP_CACHED;
        }
index ee5c4736480f1b084f7182fff54924dad496e6a1..de39e067ae65a53effae5470b12c6a31726451cf 100644 (file)
@@ -954,10 +954,11 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
        return 0;
 }
 
+WRAP_DIR_ITER(ovl_iterate) // FIXME!
 const struct file_operations ovl_dir_operations = {
        .read           = generic_read_dir,
        .open           = ovl_dir_open,
-       .iterate        = ovl_iterate,
+       .iterate_shared = shared_ovl_iterate,
        .llseek         = ovl_dir_llseek,
        .fsync          = ovl_dir_fsync,
        .release        = ovl_dir_release,
index 05452c3b9872bd00aee5c739d5e865c46d892a2a..9df3f4839662825632cd048ec1f8116bef08e1f8 100644 (file)
@@ -2817,7 +2817,7 @@ static int proc_##LSM##_attr_dir_iterate(struct file *filp, \
 \
 static const struct file_operations proc_##LSM##_attr_dir_ops = { \
        .read           = generic_read_dir, \
-       .iterate        = proc_##LSM##_attr_dir_iterate, \
+       .iterate_shared = proc_##LSM##_attr_dir_iterate, \
        .llseek         = default_llseek, \
 }; \
 \
index 9cb32e1a78a0fe382ecb83f24081575f14f6579f..23fc24d16b31e4eacadd95fff025cbc23ba4b2f7 100644 (file)
@@ -309,6 +309,8 @@ static void append_kcore_note(char *notes, size_t *i, const char *name,
 
 static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
 {
+       struct file *file = iocb->ki_filp;
+       char *buf = file->private_data;
        loff_t *fpos = &iocb->ki_pos;
        size_t phdrs_offset, notes_offset, data_offset;
        size_t page_offline_frozen = 1;
@@ -555,10 +557,21 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
                case KCORE_VMEMMAP:
                case KCORE_TEXT:
                        /*
-                        * We use _copy_to_iter() to bypass usermode hardening
-                        * which would otherwise prevent this operation.
+                        * Sadly we must use a bounce buffer here to be able to
+                        * make use of copy_from_kernel_nofault(), as these
+                        * memory regions might not always be mapped on all
+                        * architectures.
                         */
-                       if (_copy_to_iter((char *)start, tsz, iter) != tsz) {
+                       if (copy_from_kernel_nofault(buf, (void *)start, tsz)) {
+                               if (iov_iter_zero(tsz, iter) != tsz) {
+                                       ret = -EFAULT;
+                                       goto out;
+                               }
+                       /*
+                        * We know the bounce buffer is safe to copy from, so
+                        * use _copy_to_iter() directly.
+                        */
+                       } else if (_copy_to_iter(buf, tsz, iter) != tsz) {
                                ret = -EFAULT;
                                goto out;
                        }
@@ -595,6 +608,10 @@ static int open_kcore(struct inode *inode, struct file *filp)
        if (ret)
                return ret;
 
+       filp->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!filp->private_data)
+               return -ENOMEM;
+
        if (kcore_need_update)
                kcore_update_ram();
        if (i_size_read(inode) != proc_root_kcore->size) {
@@ -605,9 +622,16 @@ static int open_kcore(struct inode *inode, struct file *filp)
        return 0;
 }
 
+static int release_kcore(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       return 0;
+}
+
 static const struct proc_ops kcore_proc_ops = {
        .proc_read_iter = read_kcore_iter,
        .proc_open      = open_kcore,
+       .proc_release   = release_kcore,
        .proc_lseek     = default_llseek,
 };
 
index b264ce60114d40d154b6d569bec5335da9814a51..c8c46e29443139d1e496bbb2236e4faf6af9effa 100644 (file)
 
 #include <asm/unaligned.h>
 
+/*
+ * Some filesystems were never converted to '->iterate_shared()'
+ * and their directory iterators want the inode lock held for
+ * writing. This wrapper allows for converting from the shared
+ * semantics to the exclusive inode use.
+ */
+int wrap_directory_iterator(struct file *file,
+                           struct dir_context *ctx,
+                           int (*iter)(struct file *, struct dir_context *))
+{
+       struct inode *inode = file_inode(file);
+       int ret;
+
+       /*
+        * We'd love to have an 'inode_upgrade_trylock()' operation,
+        * see the comment in mmap_upgrade_trylock() in mm/memory.c.
+        *
+        * But considering this is for "filesystems that never got
+        * converted", it really doesn't matter.
+        *
+        * Also note that since we have to return with the lock held
+        * for reading, we can't use the "killable()" locking here,
+        * since we do need to get the lock even if we're dying.
+        *
+        * We could do the write part killably and then get the read
+        * lock unconditionally if it mattered, but see above on why
+        * this does the very simplistic conversion.
+        */
+       up_read(&inode->i_rwsem);
+       down_write(&inode->i_rwsem);
+
+       /*
+        * Since we dropped the inode lock, we should do the
+        * DEADDIR test again. See 'iterate_dir()' below.
+        *
+        * Note that we don't need to re-do the f_pos games,
+        * since the file must be locked wrt f_pos anyway.
+        */
+       ret = -ENOENT;
+       if (!IS_DEADDIR(inode))
+               ret = iter(file, ctx);
+
+       downgrade_write(&inode->i_rwsem);
+       return ret;
+}
+EXPORT_SYMBOL(wrap_directory_iterator);
+
 /*
  * Note the "unsafe_put_user() semantics: we goto a
  * label for errors.
 int iterate_dir(struct file *file, struct dir_context *ctx)
 {
        struct inode *inode = file_inode(file);
-       bool shared = false;
        int res = -ENOTDIR;
-       if (file->f_op->iterate_shared)
-               shared = true;
-       else if (!file->f_op->iterate)
+
+       if (!file->f_op->iterate_shared)
                goto out;
 
        res = security_file_permission(file, MAY_READ);
        if (res)
                goto out;
 
-       if (shared)
-               res = down_read_killable(&inode->i_rwsem);
-       else
-               res = down_write_killable(&inode->i_rwsem);
+       res = down_read_killable(&inode->i_rwsem);
        if (res)
                goto out;
 
        res = -ENOENT;
        if (!IS_DEADDIR(inode)) {
                ctx->pos = file->f_pos;
-               if (shared)
-                       res = file->f_op->iterate_shared(file, ctx);
-               else
-                       res = file->f_op->iterate(file, ctx);
+               res = file->f_op->iterate_shared(file, ctx);
                file->f_pos = ctx->pos;
                fsnotify_access(file);
                file_accessed(file);
        }
-       if (shared)
-               inode_unlock_shared(inode);
-       else
-               inode_unlock(inode);
+       inode_unlock_shared(inode);
 out:
        return res;
 }
index fb4162a52844adfdd4a8d5bafffe9c0ae75cf720..aec6e9137474217bbe67d9b61be72689a1ac78ae 100644 (file)
@@ -153,6 +153,11 @@ cifs_dump_channel(struct seq_file *m, int i, struct cifs_chan *chan)
                   in_flight(server),
                   atomic_read(&server->in_send),
                   atomic_read(&server->num_waiters));
+#ifdef CONFIG_NET_NS
+       if (server->net)
+               seq_printf(m, " Net namespace: %u ", server->net->ns.inum);
+#endif /* NET_NS */
+
 }
 
 static inline const char *smb_speed_to_str(size_t bps)
@@ -430,10 +435,15 @@ skip_rdma:
                                server->reconnect_instance,
                                server->srv_count,
                                server->sec_mode, in_flight(server));
+#ifdef CONFIG_NET_NS
+               if (server->net)
+                       seq_printf(m, " Net namespace: %u ", server->net->ns.inum);
+#endif /* NET_NS */
 
                seq_printf(m, "\nIn Send: %d In MaxReq Wait: %d",
                                atomic_read(&server->in_send),
                                atomic_read(&server->num_waiters));
+
                if (server->leaf_fullpath) {
                        seq_printf(m, "\nDFS leaf full path: %s",
                                   server->leaf_fullpath);
index df3fd3b720dac3f2cdde9c7bff587f51d33438a1..ee772c3d9f007e977c48e9debc887470951c57d1 100644 (file)
@@ -177,8 +177,12 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
                struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
 
                rc = dfs_get_referral(mnt_ctx, ref_path + 1, NULL, &tl);
-               if (rc)
+               if (rc) {
+                       rc = cifs_mount_get_tcon(mnt_ctx);
+                       if (!rc)
+                               rc = cifs_is_path_remote(mnt_ctx);
                        break;
+               }
 
                tit = dfs_cache_get_tgt_iterator(&tl);
                if (!tit) {
index fc5acc95cd13f9ea30223985b9b9132f76f578c5..6bc44f79d2e90136432fd0c8a3193331977eb779 100644 (file)
@@ -4681,9 +4681,9 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
 
 io_error:
        kunmap(page);
-       unlock_page(page);
 
 read_complete:
+       unlock_page(page);
        return rc;
 }
 
@@ -4878,9 +4878,11 @@ void cifs_oplock_break(struct work_struct *work)
        struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
                                                  oplock_break);
        struct inode *inode = d_inode(cfile->dentry);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct cifsInodeInfo *cinode = CIFS_I(inode);
-       struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
-       struct TCP_Server_Info *server = tcon->ses->server;
+       struct cifs_tcon *tcon;
+       struct TCP_Server_Info *server;
+       struct tcon_link *tlink;
        int rc = 0;
        bool purge_cache = false, oplock_break_cancelled;
        __u64 persistent_fid, volatile_fid;
@@ -4889,6 +4891,12 @@ void cifs_oplock_break(struct work_struct *work)
        wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
                        TASK_UNINTERRUPTIBLE);
 
+       tlink = cifs_sb_tlink(cifs_sb);
+       if (IS_ERR(tlink))
+               goto out;
+       tcon = tlink_tcon(tlink);
+       server = tcon->ses->server;
+
        server->ops->downgrade_oplock(server, cinode, cfile->oplock_level,
                                      cfile->oplock_epoch, &purge_cache);
 
@@ -4938,18 +4946,19 @@ oplock_break_ack:
        /*
         * MS-SMB2 3.2.5.19.1 and 3.2.5.19.2 (and MS-CIFS 3.2.5.42) do not require
         * an acknowledgment to be sent when the file has already been closed.
-        * check for server null, since can race with kill_sb calling tree disconnect.
         */
        spin_lock(&cinode->open_file_lock);
-       if (tcon->ses && tcon->ses->server && !oplock_break_cancelled &&
-                                       !list_empty(&cinode->openFileList)) {
+       /* check list empty since can race with kill_sb calling tree disconnect */
+       if (!oplock_break_cancelled && !list_empty(&cinode->openFileList)) {
                spin_unlock(&cinode->open_file_lock);
-               rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid,
-                                               volatile_fid, net_fid, cinode);
+               rc = server->ops->oplock_response(tcon, persistent_fid,
+                                                 volatile_fid, net_fid, cinode);
                cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
        } else
                spin_unlock(&cinode->open_file_lock);
 
+       cifs_put_tlink(tlink);
+out:
        cifs_done_oplock_break(cinode);
 }
 
index 4946a0c59600928b9331cca3b392ba6e30a48da6..67e16c2ac90e6f7b2d34418cae4b0b936ccaf29f 100644 (file)
@@ -231,6 +231,8 @@ cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_c
                break;
        case Opt_sec_none:
                ctx->nullauth = 1;
+               kfree(ctx->username);
+               ctx->username = NULL;
                break;
        default:
                cifs_errorf(fc, "bad security option: %s\n", value);
@@ -1201,6 +1203,8 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
        case Opt_user:
                kfree(ctx->username);
                ctx->username = NULL;
+               if (ctx->nullauth)
+                       break;
                if (strlen(param->string) == 0) {
                        /* null user, ie. anonymous authentication */
                        ctx->nullauth = 1;
index 33b7e6c4ceffb6d6fc58dab949ac5e1cef252605..e881df1d10cbd58ba1be08556a15c13c3d1a06db 100644 (file)
@@ -380,13 +380,13 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
        }
 
        if (smb2_req_struct_sizes[command] != pdu->StructureSize2) {
-               if (command == SMB2_OPLOCK_BREAK_HE &&
-                   le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 &&
-                   le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) {
+               if (!(command == SMB2_OPLOCK_BREAK_HE &&
+                   (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 ||
+                   le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_21))) {
                        /* special case for SMB2.1 lease break message */
                        ksmbd_debug(SMB,
-                                   "Illegal request size %d for oplock break\n",
-                                   le16_to_cpu(pdu->StructureSize2));
+                               "Illegal request size %u for command %d\n",
+                               le16_to_cpu(pdu->StructureSize2), command);
                        return 1;
                }
        }
index 9849d748934599f3ced31b6c5b1317ddc8c1c7ad..7cc1b0c47d0a2069eab845cb8cdc14ae77c8bac2 100644 (file)
@@ -2324,9 +2324,16 @@ next:
                        break;
                buf_len -= next;
                eabuf = (struct smb2_ea_info *)((char *)eabuf + next);
-               if (next < (u32)eabuf->EaNameLength + le16_to_cpu(eabuf->EaValueLength))
+               if (buf_len < sizeof(struct smb2_ea_info)) {
+                       rc = -EINVAL;
                        break;
+               }
 
+               if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength +
+                               le16_to_cpu(eabuf->EaValueLength)) {
+                       rc = -EINVAL;
+                       break;
+               }
        } while (next != 0);
 
        kfree(attr_name);
index 075f15c43c7806baf9240cc65aa952d0cd12c9d2..5f1a14d5b92731d63514c92ac9761ec90e4eb32a 100644 (file)
@@ -179,9 +179,10 @@ static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx)
        return 0;
 }
 
+WRAP_DIR_ITER(vboxsf_dir_iterate) // FIXME!
 const struct file_operations vboxsf_dir_fops = {
        .open = vboxsf_dir_open,
-       .iterate = vboxsf_dir_iterate,
+       .iterate_shared = shared_vboxsf_dir_iterate,
        .release = vboxsf_dir_release,
        .read = generic_read_dir,
        .llseek = generic_file_llseek,
index aca829062c128b75f5762cbf4dd16ae08c4f39cf..069a019c92473f6813abf2e048fc63ca44b23718 100644 (file)
@@ -68,9 +68,9 @@ struct shfl_string {
 
        /** UTF-8 or UTF-16 string. Nul terminated. */
        union {
-               u8 utf8[2];
-               u16 utf16[1];
-               u16 ucs2[1]; /* misnomer, use utf16. */
+               u8 legacy_padding[2];
+               DECLARE_FLEX_ARRAY(u8, utf8);
+               DECLARE_FLEX_ARRAY(u16, utf16);
        } string;
 };
 VMMDEV_ASSERT_SIZE(shfl_string, 6);
index 92c9aaae3663dd70ea555d12745e9e62e5f8978d..789cfb74c1463ea1112cb094cb88241b230e84e9 100644 (file)
@@ -341,77 +341,6 @@ static loff_t zonefs_file_llseek(struct file *file, loff_t offset, int whence)
        return generic_file_llseek_size(file, offset, whence, isize, isize);
 }
 
-struct zonefs_zone_append_bio {
-       /* The target inode of the BIO */
-       struct inode *inode;
-
-       /* For sync writes, the target append write offset */
-       u64 append_offset;
-
-       /*
-        * This member must come last, bio_alloc_bioset will allocate enough
-        * bytes for entire zonefs_bio but relies on bio being last.
-        */
-       struct bio bio;
-};
-
-static inline struct zonefs_zone_append_bio *
-zonefs_zone_append_bio(struct bio *bio)
-{
-       return container_of(bio, struct zonefs_zone_append_bio, bio);
-}
-
-static void zonefs_file_zone_append_dio_bio_end_io(struct bio *bio)
-{
-       struct zonefs_zone_append_bio *za_bio = zonefs_zone_append_bio(bio);
-       struct zonefs_zone *z = zonefs_inode_zone(za_bio->inode);
-       sector_t za_sector;
-
-       if (bio->bi_status != BLK_STS_OK)
-               goto bio_end;
-
-       /*
-        * If the file zone was written underneath the file system, the zone
-        * append operation can still succedd (if the zone is not full) but
-        * the write append location will not be where we expect it to be.
-        * Check that we wrote where we intended to, that is, at z->z_wpoffset.
-        */
-       za_sector = z->z_sector + (za_bio->append_offset >> SECTOR_SHIFT);
-       if (bio->bi_iter.bi_sector != za_sector) {
-               zonefs_warn(za_bio->inode->i_sb,
-                           "Invalid write sector %llu for zone at %llu\n",
-                           bio->bi_iter.bi_sector, z->z_sector);
-               bio->bi_status = BLK_STS_IOERR;
-       }
-
-bio_end:
-       iomap_dio_bio_end_io(bio);
-}
-
-static void zonefs_file_zone_append_dio_submit_io(const struct iomap_iter *iter,
-                                                 struct bio *bio,
-                                                 loff_t file_offset)
-{
-       struct zonefs_zone_append_bio *za_bio = zonefs_zone_append_bio(bio);
-       struct inode *inode = iter->inode;
-       struct zonefs_zone *z = zonefs_inode_zone(inode);
-
-       /*
-        * Issue a zone append BIO to process sync dio writes. The append
-        * file offset is saved to check the zone append write location
-        * on completion of the BIO.
-        */
-       za_bio->inode = inode;
-       za_bio->append_offset = file_offset;
-
-       bio->bi_opf &= ~REQ_OP_WRITE;
-       bio->bi_opf |= REQ_OP_ZONE_APPEND;
-       bio->bi_iter.bi_sector = z->z_sector;
-       bio->bi_end_io = zonefs_file_zone_append_dio_bio_end_io;
-
-       submit_bio(bio);
-}
-
 static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
                                        int error, unsigned int flags)
 {
@@ -442,14 +371,6 @@ static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
        return 0;
 }
 
-static struct bio_set zonefs_zone_append_bio_set;
-
-static const struct iomap_dio_ops zonefs_zone_append_dio_ops = {
-       .submit_io      = zonefs_file_zone_append_dio_submit_io,
-       .end_io         = zonefs_file_write_dio_end_io,
-       .bio_set        = &zonefs_zone_append_bio_set,
-};
-
 static const struct iomap_dio_ops zonefs_write_dio_ops = {
        .end_io         = zonefs_file_write_dio_end_io,
 };
@@ -533,9 +454,6 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
        struct zonefs_inode_info *zi = ZONEFS_I(inode);
        struct zonefs_zone *z = zonefs_inode_zone(inode);
        struct super_block *sb = inode->i_sb;
-       const struct iomap_dio_ops *dio_ops;
-       bool sync = is_sync_kiocb(iocb);
-       bool append = false;
        ssize_t ret, count;
 
        /*
@@ -543,7 +461,8 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
         * as this can cause write reordering (e.g. the first aio gets EAGAIN
         * on the inode lock but the second goes through but is now unaligned).
         */
-       if (zonefs_zone_is_seq(z) && !sync && (iocb->ki_flags & IOCB_NOWAIT))
+       if (zonefs_zone_is_seq(z) && !is_sync_kiocb(iocb) &&
+           (iocb->ki_flags & IOCB_NOWAIT))
                return -EOPNOTSUPP;
 
        if (iocb->ki_flags & IOCB_NOWAIT) {
@@ -573,18 +492,6 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
                        goto inode_unlock;
                }
                mutex_unlock(&zi->i_truncate_mutex);
-               append = sync;
-       }
-
-       if (append) {
-               unsigned int max = bdev_max_zone_append_sectors(sb->s_bdev);
-
-               max = ALIGN_DOWN(max << SECTOR_SHIFT, sb->s_blocksize);
-               iov_iter_truncate(from, max);
-
-               dio_ops = &zonefs_zone_append_dio_ops;
-       } else {
-               dio_ops = &zonefs_write_dio_ops;
        }
 
        /*
@@ -593,7 +500,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
         * the user can make sense of the error.
         */
        ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops,
-                          dio_ops, 0, NULL, 0);
+                          &zonefs_write_dio_ops, 0, NULL, 0);
        if (ret == -ENOTBLK)
                ret = -EBUSY;
 
@@ -938,15 +845,3 @@ const struct file_operations zonefs_file_operations = {
        .splice_write   = iter_file_splice_write,
        .iopoll         = iocb_bio_iopoll,
 };
-
-int zonefs_file_bioset_init(void)
-{
-       return bioset_init(&zonefs_zone_append_bio_set, BIO_POOL_SIZE,
-                          offsetof(struct zonefs_zone_append_bio, bio),
-                          BIOSET_NEED_BVECS);
-}
-
-void zonefs_file_bioset_exit(void)
-{
-       bioset_exit(&zonefs_zone_append_bio_set);
-}
index bbe44a26a8e591f580398351abafb5525d4499cf..9350221abfc55196cd0a824eeaa91869cd97ece1 100644 (file)
@@ -1412,13 +1412,9 @@ static int __init zonefs_init(void)
 
        BUILD_BUG_ON(sizeof(struct zonefs_super) != ZONEFS_SUPER_SIZE);
 
-       ret = zonefs_file_bioset_init();
-       if (ret)
-               return ret;
-
        ret = zonefs_init_inodecache();
        if (ret)
-               goto destroy_bioset;
+               return ret;
 
        ret = zonefs_sysfs_init();
        if (ret)
@@ -1434,8 +1430,6 @@ sysfs_exit:
        zonefs_sysfs_exit();
 destroy_inodecache:
        zonefs_destroy_inodecache();
-destroy_bioset:
-       zonefs_file_bioset_exit();
 
        return ret;
 }
@@ -1445,7 +1439,6 @@ static void __exit zonefs_exit(void)
        unregister_filesystem(&zonefs_type);
        zonefs_sysfs_exit();
        zonefs_destroy_inodecache();
-       zonefs_file_bioset_exit();
 }
 
 MODULE_AUTHOR("Damien Le Moal");
index f663b8ebc2cbf08cb2859756dfcbe0daf3939639..8175652241b5c4104748d8a75fcbd59e58ef1e88 100644 (file)
@@ -279,8 +279,6 @@ extern const struct file_operations zonefs_dir_operations;
 extern const struct address_space_operations zonefs_file_aops;
 extern const struct file_operations zonefs_file_operations;
 int zonefs_file_truncate(struct inode *inode, loff_t isize);
-int zonefs_file_bioset_init(void);
-void zonefs_file_bioset_exit(void);
 
 /* In sysfs.c */
 int zonefs_sysfs_register(struct super_block *sb);
index d71291f25a80b3f7a5c8fb5d834b34d263338582..76aa6aa346ba28f56106b7bf5f51f3e44592bd9e 100644 (file)
@@ -22,6 +22,7 @@
 #define METHOD_NAME__DDN        "_DDN"
 #define METHOD_NAME__DIS        "_DIS"
 #define METHOD_NAME__DMA        "_DMA"
+#define METHOD_NAME__EVT        "_EVT"
 #define METHOD_NAME__HID        "_HID"
 #define METHOD_NAME__INI        "_INI"
 #define METHOD_NAME__PLD        "_PLD"
index 449ec8a015bfd32dd917ec7b4a921f367c27d68b..254685085c825c84fecd23e81a3c420056b66ffd 100644 (file)
@@ -515,6 +515,12 @@ void acpi_bus_private_data_handler(acpi_handle, void *);
 int acpi_bus_get_private_data(acpi_handle, void **);
 int acpi_bus_attach_private_data(acpi_handle, void *);
 void acpi_bus_detach_private_data(acpi_handle);
+int acpi_dev_install_notify_handler(struct acpi_device *adev,
+                                   u32 handler_type,
+                                   acpi_notify_handler handler);
+void acpi_dev_remove_notify_handler(struct acpi_device *adev,
+                                   u32 handler_type,
+                                   acpi_notify_handler handler);
 extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
 extern int register_acpi_notifier(struct notifier_block *);
 extern int unregister_acpi_notifier(struct notifier_block *);
@@ -643,6 +649,8 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev);
 #ifdef CONFIG_X86
 bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status);
 bool acpi_quirk_skip_acpi_ac_and_battery(void);
+int acpi_install_cmos_rtc_space_handler(acpi_handle handle);
+void acpi_remove_cmos_rtc_space_handler(acpi_handle handle);
 #else
 static inline bool acpi_device_override_status(struct acpi_device *adev,
                                               unsigned long long *status)
@@ -653,6 +661,13 @@ static inline bool acpi_quirk_skip_acpi_ac_and_battery(void)
 {
        return false;
 }
+static inline int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
+{
+       return 1;
+}
+static inline void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
+{
+}
 #endif
 
 #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
index cb64010cc5d8a2789d3d465d65527296a60314b7..3d90716f9522960a6902f5adc645b09e2debe5e3 100644 (file)
@@ -12,7 +12,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20230331
+#define ACPI_CA_VERSION                 0x20230628
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
index 58b0490a2ad12e26cab30209e461429a1f5dec30..8d5572ad48cbea6ff701e8185447aa918ab123b1 100644 (file)
@@ -402,7 +402,7 @@ struct acpi_cdat_dsmas {
 
 /* Flags for subtable above */
 
-#define ACPI_CEDT_DSMAS_NON_VOLATILE        (1 << 2)
+#define ACPI_CDAT_DSMAS_NON_VOLATILE        (1 << 2)
 
 /* Subtable 1: Device scoped Latency and Bandwidth Information Structure (DSLBIS) */
 
index 0029336775a917790bc300fffd10e322836974b0..3751ae69432f1285533a61db8e0c31d42ed5fa31 100644 (file)
@@ -893,7 +893,10 @@ enum acpi_madt_type {
        ACPI_MADT_TYPE_BIO_PIC = 22,
        ACPI_MADT_TYPE_LPC_PIC = 23,
        ACPI_MADT_TYPE_RINTC = 24,
-       ACPI_MADT_TYPE_RESERVED = 25,   /* 25 to 0x7F are reserved */
+       ACPI_MADT_TYPE_IMSIC = 25,
+       ACPI_MADT_TYPE_APLIC = 26,
+       ACPI_MADT_TYPE_PLIC = 27,
+       ACPI_MADT_TYPE_RESERVED = 28,   /* 28 to 0x7F are reserved */
        ACPI_MADT_TYPE_OEM_RESERVED = 0x80      /* 0x80 to 0xFF are reserved for OEM use */
 };
 
@@ -1261,6 +1264,9 @@ struct acpi_madt_rintc {
        u32 flags;
        u64 hart_id;
        u32 uid;                /* ACPI processor UID */
+       u32 ext_intc_id;        /* External INTC Id */
+       u64 imsic_addr;         /* IMSIC base address */
+       u32 imsic_size;         /* IMSIC size */
 };
 
 /* Values for RISC-V INTC Version field above */
@@ -1271,6 +1277,48 @@ enum acpi_madt_rintc_version {
        ACPI_MADT_RINTC_VERSION_RESERVED = 2    /* 2 and greater are reserved */
 };
 
+/* 25: RISC-V IMSIC */
+struct acpi_madt_imsic {
+       struct acpi_subtable_header header;
+       u8 version;
+       u8 reserved;
+       u32 flags;
+       u16 num_ids;
+       u16 num_guest_ids;
+       u8 guest_index_bits;
+       u8 hart_index_bits;
+       u8 group_index_bits;
+       u8 group_index_shift;
+};
+
+/* 26: RISC-V APLIC */
+struct acpi_madt_aplic {
+       struct acpi_subtable_header header;
+       u8 version;
+       u8 id;
+       u32 flags;
+       u8 hw_id[8];
+       u16 num_idcs;
+       u16 num_sources;
+       u32 gsi_base;
+       u64 base_addr;
+       u32 size;
+};
+
+/* 27: RISC-V PLIC */
+struct acpi_madt_plic {
+       struct acpi_subtable_header header;
+       u8 version;
+       u8 id;
+       u8 hw_id[8];
+       u16 num_irqs;
+       u16 max_prio;
+       u32 flags;
+       u32 size;
+       u64 base_addr;
+       u32 gsi_base;
+};
+
 /* 80: OEM data */
 
 struct acpi_madt_oem_data {
@@ -2730,12 +2778,15 @@ enum acpi_rgrt_image_type {
 
 struct acpi_table_rhct {
        struct acpi_table_header header;        /* Common ACPI table header */
-       u32 reserved;
+       u32 flags;              /* RHCT flags */
        u64 time_base_freq;
        u32 node_count;
        u32 node_offset;
 };
 
+/* RHCT Flags */
+
+#define ACPI_RHCT_TIMER_CANNOT_WAKEUP_CPU       (1)
 /*
  * RHCT subtables
  */
@@ -2749,6 +2800,9 @@ struct acpi_rhct_node_header {
 
 enum acpi_rhct_node_type {
        ACPI_RHCT_NODE_TYPE_ISA_STRING = 0x0000,
+       ACPI_RHCT_NODE_TYPE_CMO = 0x0001,
+       ACPI_RHCT_NODE_TYPE_MMU = 0x0002,
+       ACPI_RHCT_NODE_TYPE_RESERVED = 0x0003,
        ACPI_RHCT_NODE_TYPE_HART_INFO = 0xFFFF,
 };
 
@@ -2762,6 +2816,24 @@ struct acpi_rhct_isa_string {
        char isa[];
 };
 
+struct acpi_rhct_cmo_node {
+       u8 reserved;            /* Must be zero */
+       u8 cbom_size;           /* CBOM size in powerof 2 */
+       u8 cbop_size;           /* CBOP size in powerof 2 */
+       u8 cboz_size;           /* CBOZ size in powerof 2 */
+};
+
+struct acpi_rhct_mmu_node {
+       u8 reserved;            /* Must be zero */
+       u8 mmu_type;            /* Virtual Address Scheme */
+};
+
+enum acpi_rhct_mmu_type {
+       ACPI_RHCT_MMU_TYPE_SV39 = 0,
+       ACPI_RHCT_MMU_TYPE_SV48 = 1,
+       ACPI_RHCT_MMU_TYPE_SV57 = 2
+};
+
 /* Hart Info node structure */
 struct acpi_rhct_hart_info {
        u16 num_offsets;
index 000764ab398565f71c8139c25981fc6fefdf1aa8..c080d579a54624af1c412ce2f388db0b1f3248bd 100644 (file)
@@ -279,12 +279,14 @@ struct acpi_srat_gic_its_affinity {
  * 6: ACPI_SRAT_TYPE_GENERIC_PORT_AFFINITY
  */
 
+#define ACPI_SRAT_DEVICE_HANDLE_SIZE   16
+
 struct acpi_srat_generic_affinity {
        struct acpi_subtable_header header;
        u8 reserved;
        u8 device_handle_type;
        u32 proximity_domain;
-       u8 device_handle[16];
+       u8 device_handle[ACPI_SRAT_DEVICE_HANDLE_SIZE];
        u32 flags;
        u32 reserved1;
 };
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h
deleted file mode 100644 (file)
index 967c552..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-/* _PDC bit definition for Intel processors */
-
-#ifndef __PDC_INTEL_H__
-#define __PDC_INTEL_H__
-
-#define ACPI_PDC_P_FFH                 (0x0001)
-#define ACPI_PDC_C_C1_HALT             (0x0002)
-#define ACPI_PDC_T_FFH                 (0x0004)
-#define ACPI_PDC_SMP_C1PT              (0x0008)
-#define ACPI_PDC_SMP_C2C3              (0x0010)
-#define ACPI_PDC_SMP_P_SWCOORD         (0x0020)
-#define ACPI_PDC_SMP_C_SWCOORD         (0x0040)
-#define ACPI_PDC_SMP_T_SWCOORD         (0x0080)
-#define ACPI_PDC_C_C1_FFH              (0x0100)
-#define ACPI_PDC_C_C2C3_FFH            (0x0200)
-#define ACPI_PDC_SMP_P_HWCOORD         (0x0800)
-
-#define ACPI_PDC_EST_CAPABILITY_SMP    (ACPI_PDC_SMP_C1PT | \
-                                        ACPI_PDC_C_C1_HALT | \
-                                        ACPI_PDC_P_FFH)
-
-#define ACPI_PDC_EST_CAPABILITY_SWSMP  (ACPI_PDC_SMP_C1PT | \
-                                        ACPI_PDC_C_C1_HALT | \
-                                        ACPI_PDC_SMP_P_SWCOORD | \
-                                        ACPI_PDC_SMP_P_HWCOORD | \
-                                        ACPI_PDC_P_FFH)
-
-#define ACPI_PDC_C_CAPABILITY_SMP      (ACPI_PDC_SMP_C2C3  | \
-                                        ACPI_PDC_SMP_C1PT  | \
-                                        ACPI_PDC_C_C1_HALT | \
-                                        ACPI_PDC_C_C1_FFH  | \
-                                        ACPI_PDC_C_C2C3_FFH)
-
-#endif                         /* __PDC_INTEL_H__ */
index 1ca450e35c0d5dabc9865cba854a981852e1e83d..565341c826e38be71e73624512d50846c8032520 100644 (file)
 #ifdef ACPI_USE_STANDARD_HEADERS
 #include <stddef.h>
 #include <unistd.h>
+#include <stdint.h>
 
 #define ACPI_OFFSET(d, f)   offsetof(d, f)
 #endif
index 2f0d30c3c5fd24fb679d80d99e5a02f036097abd..703db4dc740d8dacddba836d30ef72ff506dbf9d 100644 (file)
@@ -10,9 +10,6 @@
 #ifndef __ACZEPHYR_H__
 #define __ACZEPHYR_H__
 
-#define SEEK_SET FS_SEEK_SET
-#define SEEK_END FS_SEEK_END
-
 #define ACPI_MACHINE_WIDTH      64
 
 #define ACPI_NO_ERROR_MESSAGES
diff --git a/include/acpi/proc_cap_intel.h b/include/acpi/proc_cap_intel.h
new file mode 100644 (file)
index 0000000..ddcdc41
--- /dev/null
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* Vendor specific processor capabilities bit definition
+ * for Intel processors. Those bits are used to convey OSPM
+ * power management capabilities to the platform.
+ */
+
+#ifndef __PROC_CAP_INTEL_H__
+#define __PROC_CAP_INTEL_H__
+
+#define ACPI_PROC_CAP_P_FFH                    (0x0001)
+#define ACPI_PROC_CAP_C_C1_HALT                        (0x0002)
+#define ACPI_PROC_CAP_T_FFH                    (0x0004)
+#define ACPI_PROC_CAP_SMP_C1PT                 (0x0008)
+#define ACPI_PROC_CAP_SMP_C2C3                 (0x0010)
+#define ACPI_PROC_CAP_SMP_P_SWCOORD            (0x0020)
+#define ACPI_PROC_CAP_SMP_C_SWCOORD            (0x0040)
+#define ACPI_PROC_CAP_SMP_T_SWCOORD            (0x0080)
+#define ACPI_PROC_CAP_C_C1_FFH                 (0x0100)
+#define ACPI_PROC_CAP_C_C2C3_FFH               (0x0200)
+#define ACPI_PROC_CAP_SMP_P_HWCOORD            (0x0800)
+#define ACPI_PROC_CAP_COLLAB_PROC_PERF         (0x1000)
+
+#define ACPI_PROC_CAP_EST_CAPABILITY_SMP       (ACPI_PROC_CAP_SMP_C1PT | \
+                                                ACPI_PROC_CAP_C_C1_HALT | \
+                                                ACPI_PROC_CAP_P_FFH)
+
+#define ACPI_PROC_CAP_EST_CAPABILITY_SWSMP     (ACPI_PROC_CAP_SMP_C1PT | \
+                                                ACPI_PROC_CAP_C_C1_HALT | \
+                                                ACPI_PROC_CAP_SMP_P_SWCOORD | \
+                                                ACPI_PROC_CAP_SMP_P_HWCOORD | \
+                                                ACPI_PROC_CAP_P_FFH)
+
+#define ACPI_PROC_CAP_C_CAPABILITY_SMP         (ACPI_PROC_CAP_SMP_C2C3  | \
+                                                ACPI_PROC_CAP_SMP_C1PT  | \
+                                                ACPI_PROC_CAP_C_C1_HALT | \
+                                                ACPI_PROC_CAP_C_C1_FFH  | \
+                                                ACPI_PROC_CAP_C_C2C3_FFH)
+
+#endif /* __PROC_CAP_INTEL_H__ */
index 402a8c1c202db4fb248f1ac0669a90a191efd754..a8f4b653ef4ee161abd5e3ef7fbe2de951332952 100644 (file)
@@ -190,7 +190,7 @@ int hv_common_cpu_die(unsigned int cpu);
 
 void *hv_alloc_hyperv_page(void);
 void *hv_alloc_hyperv_zeroed_page(void);
-void hv_free_hyperv_page(unsigned long addr);
+void hv_free_hyperv_page(void *addr);
 
 /**
  * hv_cpu_number_to_vp_number() - Map CPU to VP.
index 20c93f08c9933b81d4a362701d30cd7fda5106d6..95a1d214108a5d38f01fb98108028f321e3c6d4e 100644 (file)
@@ -38,7 +38,7 @@ static inline long find_zero(unsigned long mask)
        return (mask >> 8) ? byte : byte + 1;
 }
 
-static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
+static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
 {
        unsigned long rhs = val | c->low_bits;
        *data = rhs;
index 169755d3de1908e530b0cbb7531103eacbe75878..48e93f909ef6fec10933d2530e6c0c8349f2b518 100644 (file)
@@ -61,15 +61,9 @@ struct std_timing {
        u8 vfreq_aspect;
 } __attribute__((packed));
 
-#define DRM_EDID_PT_SYNC_MASK              (3 << 3)
-# define DRM_EDID_PT_ANALOG_CSYNC          (0 << 3)
-# define DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC  (1 << 3)
-# define DRM_EDID_PT_DIGITAL_CSYNC         (2 << 3)
-#  define DRM_EDID_PT_CSYNC_ON_RGB         (1 << 1) /* analog csync only */
-#  define DRM_EDID_PT_CSYNC_SERRATE        (1 << 2)
-# define DRM_EDID_PT_DIGITAL_SEPARATE_SYNC (3 << 3)
-#  define DRM_EDID_PT_HSYNC_POSITIVE       (1 << 1) /* also digital csync */
-#  define DRM_EDID_PT_VSYNC_POSITIVE       (1 << 2)
+#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
+#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
+#define DRM_EDID_PT_SEPARATE_SYNC  (3 << 3)
 #define DRM_EDID_PT_STEREO         (1 << 5)
 #define DRM_EDID_PT_INTERLACED     (1 << 7)
 
index c4f5b5228105fe2a7f8c322da3a511cf44e5697c..11984ed29cb8f372ed5cf58511cbf80232965d0c 100644 (file)
@@ -791,7 +791,7 @@ static inline int bio_integrity_add_page(struct bio *bio, struct page *page,
 static inline void bio_set_polled(struct bio *bio, struct kiocb *kiocb)
 {
        bio->bi_opf |= REQ_POLLED;
-       if (!is_sync_kiocb(kiocb))
+       if (kiocb->ki_flags & IOCB_NOWAIT)
                bio->bi_opf |= REQ_NOWAIT;
 }
 
index ed44a997f629f5dd1829d0529f6762e78bacc828..87d94be7825afa272f1f4a432eca3080604d633e 100644 (file)
@@ -969,7 +969,6 @@ struct blk_plug {
 
        bool multiple_queues;
        bool has_elevator;
-       bool nowait;
 
        struct list_head cb_list; /* md requires an unplug callback */
 };
index 6e6e57ec69e84db48f4a68dbb6a3ed9d25727fa6..e006c719182bac98901586d58d4dea4d6e351b61 100644 (file)
@@ -70,6 +70,10 @@ extern ssize_t cpu_show_mmio_stale_data(struct device *dev,
                                        char *buf);
 extern ssize_t cpu_show_retbleed(struct device *dev,
                                 struct device_attribute *attr, char *buf);
+extern ssize_t cpu_show_spec_rstack_overflow(struct device *dev,
+                                            struct device_attribute *attr, char *buf);
+extern ssize_t cpu_show_gds(struct device *dev,
+                           struct device_attribute *attr, char *buf);
 
 extern __printf(4, 5)
 struct device *cpu_device_create(struct device *parent, void *drvdata,
index 0d2e2a38b92d0d115f5d4d6a1d37b7400347ba0a..f10fb87d49dbe38bf220857202c9a2ece8e9f31e 100644 (file)
@@ -175,8 +175,8 @@ static inline unsigned int cpumask_first_zero(const struct cpumask *srcp)
 
 /**
  * cpumask_first_and - return the first cpu from *srcp1 & *srcp2
- * @src1p: the first input
- * @src2p: the second input
+ * @srcp1: the first input
+ * @srcp2: the second input
  *
  * Returns >= nr_cpu_ids if no cpus set in both.  See also cpumask_next_and().
  */
@@ -1197,6 +1197,10 @@ cpumap_print_bitmask_to_buf(char *buf, const struct cpumask *mask,
 /**
  * cpumap_print_list_to_buf  - copies the cpumask into the buffer as
  *     comma-separated list of cpus
+ * @buf: the buffer to copy into
+ * @mask: the cpumask to copy
+ * @off: in the string from which we are copying, we copy to @buf
+ * @count: the maximum number of bytes to print
  *
  * Everything is same with the above cpumap_print_bitmask_to_buf()
  * except the print format.
index 6867512907d6e593ec18cbd27dc52471b66418a0..562f2623c9c9f4a440d81ed4a0dc1bbe269d06fb 100644 (file)
@@ -1780,7 +1780,6 @@ struct file_operations {
        ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
        int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *,
                        unsigned int flags);
-       int (*iterate) (struct file *, struct dir_context *);
        int (*iterate_shared) (struct file *, struct dir_context *);
        __poll_t (*poll) (struct file *, struct poll_table_struct *);
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
@@ -1817,6 +1816,13 @@ struct file_operations {
                                unsigned int poll_flags);
 } __randomize_layout;
 
+/* Wrap a directory iterator that needs exclusive inode access */
+int wrap_directory_iterator(struct file *, struct dir_context *,
+                           int (*) (struct file *, struct dir_context *));
+#define WRAP_DIR_ITER(x) \
+       static int shared_##x(struct file *file , struct dir_context *ctx) \
+       { return wrap_directory_iterator(file, ctx, x); }
+
 struct inode_operations {
        struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
        const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);
index bfbc37ce223b03f3f138556104ec4fb871b57e28..3ac3974b3c7819053b07e7aa423d9153dfbbe186 100644 (file)
@@ -1239,9 +1239,6 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
                                     u32 *buffer_actual_len,
                                     u64 *requestid);
 
-
-extern void vmbus_ontimer(unsigned long data);
-
 /* Base driver object */
 struct hv_driver {
        const char *name;
index e6936cb2504719864e232b8fdd32e0d936257a34..33f21bd85dbf273eb98b4095e81351c57894af9d 100644 (file)
@@ -100,10 +100,16 @@ struct rapl_package;
 
 #define RAPL_DOMAIN_NAME_LENGTH 16
 
+union rapl_reg {
+       void __iomem *mmio;
+       u32 msr;
+       u64 val;
+};
+
 struct rapl_domain {
        char name[RAPL_DOMAIN_NAME_LENGTH];
        enum rapl_domain_type id;
-       u64 regs[RAPL_DOMAIN_REG_MAX];
+       union rapl_reg regs[RAPL_DOMAIN_REG_MAX];
        struct powercap_zone power_zone;
        struct rapl_domain_data rdd;
        struct rapl_power_limit rpl[NR_POWER_LIMITS];
@@ -116,7 +122,7 @@ struct rapl_domain {
 };
 
 struct reg_action {
-       u64 reg;
+       union rapl_reg reg;
        u64 mask;
        u64 value;
        int err;
@@ -143,8 +149,8 @@ struct rapl_if_priv {
        enum rapl_if_type type;
        struct powercap_control_type *control_type;
        enum cpuhp_state pcap_rapl_online;
-       u64 reg_unit;
-       u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX];
+       union rapl_reg reg_unit;
+       union rapl_reg regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX];
        int limits[RAPL_DOMAIN_MAX];
        int (*read_raw)(int id, struct reg_action *ra);
        int (*write_raw)(int id, struct reg_action *ra);
index b83a3f944f287576a5c698bdb2e05dc714713eb2..b068e2e609393ade1dbd7b208e49cb7f29196a3b 100644 (file)
@@ -25,11 +25,10 @@ struct page;
        prefetch() should be defined by the architecture, if not, the 
        #define below provides a no-op define.  
        
-       There are 3 prefetch() macros:
+       There are 2 prefetch() macros:
        
        prefetch(x)     - prefetches the cacheline at "x" for read
        prefetchw(x)    - prefetches the cacheline at "x" for write
-       spin_lock_prefetch(x) - prefetches the spinlock *x for taking
        
        there is also PREFETCH_STRIDE which is the architecure-preferred 
        "lookahead" size for prefetching streamed operations.
@@ -44,10 +43,6 @@ struct page;
 #define prefetchw(x) __builtin_prefetch(x,1)
 #endif
 
-#ifndef ARCH_HAS_SPINLOCK_PREFETCH
-#define spin_lock_prefetch(x) prefetchw(x)
-#endif
-
 #ifndef PREFETCH_STRIDE
 #define PREFETCH_STRIDE (4*L1_CACHE_BYTES)
 #endif
index 6d58c57acdaa12d374bf415e986b4797d37694a9..a156d2ed8d9eef1c38e24a3ab5084ade7c4e635d 100644 (file)
@@ -459,7 +459,8 @@ struct uart_port {
                                                struct serial_rs485 *rs485);
        int                     (*iso7816_config)(struct uart_port *,
                                                  struct serial_iso7816 *iso7816);
-       int                     ctrl_id;                /* optional serial core controller id */
+       unsigned int            ctrl_id;                /* optional serial core controller id */
+       unsigned int            port_id;                /* optional serial core port id */
        unsigned int            irq;                    /* irq number */
        unsigned long           irqflags;               /* irq flags  */
        unsigned int            uartclk;                /* base uart clock */
index 054d7911bfc9f3430c1b7fc124b9b48ad9c391e5..c1637515a8a41613580eb6006fd17f9ad0a8733b 100644 (file)
@@ -62,6 +62,7 @@ struct sk_psock_progs {
 
 enum sk_psock_state_bits {
        SK_PSOCK_TX_ENABLED,
+       SK_PSOCK_RX_STRP_ENABLED,
 };
 
 struct sk_psock_link {
index 0b857616919c09452c8e48629564f744dcf34b2d..fc6c1515dc54c968dfb2a55039e06f55c60ef778 100644 (file)
@@ -15,4 +15,6 @@ struct corgi_lcd_platform_data {
        void (*kick_battery)(void);
 };
 
+void corgi_lcd_limit_intensity(int limit);
+
 #endif /* __LINUX_SPI_CORGI_LCD_H */
index 8e984d75f5b6cae42735670090289006b307595f..6b0a7dc48a4b799d0cfa2ed8b4534128b63c14de 100644 (file)
@@ -101,6 +101,7 @@ struct spi_mem_op {
                u8 nbytes;
                u8 buswidth;
                u8 dtr : 1;
+               u8 __pad : 7;
                u16 opcode;
        } cmd;
 
@@ -108,6 +109,7 @@ struct spi_mem_op {
                u8 nbytes;
                u8 buswidth;
                u8 dtr : 1;
+               u8 __pad : 7;
                u64 val;
        } addr;
 
@@ -115,12 +117,14 @@ struct spi_mem_op {
                u8 nbytes;
                u8 buswidth;
                u8 dtr : 1;
+               u8 __pad : 7;
        } dummy;
 
        struct {
                u8 buswidth;
                u8 dtr : 1;
                u8 ecc : 1;
+               u8 __pad : 6;
                enum spi_mem_data_dir dir;
                unsigned int nbytes;
                union {
index dee66ade89a0393be9ab2e6d3c5c342b49093d83..b449a46766f5a34535fc121d40afdd5a72c19ea0 100644 (file)
@@ -81,11 +81,13 @@ struct thermal_zone_device_ops {
  * @temperature: temperature value in miliCelsius
  * @hysteresis: relative hysteresis in miliCelsius
  * @type: trip point type
+ * @priv: pointer to driver data associated with this trip
  */
 struct thermal_trip {
        int temperature;
        int hysteresis;
        enum thermal_trip_type type;
+       void *priv;
 };
 
 struct thermal_cooling_device_ops {
@@ -287,6 +289,9 @@ int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
 int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id,
                          const struct thermal_trip *trip);
 
+int for_each_thermal_trip(struct thermal_zone_device *tz,
+                         int (*cb)(struct thermal_trip *, void *),
+                         void *data);
 int thermal_zone_get_num_trips(struct thermal_zone_device *tz);
 
 int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp);
@@ -323,6 +328,10 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
                                       struct thermal_cooling_device *);
 void thermal_zone_device_update(struct thermal_zone_device *,
                                enum thermal_notify_event);
+void thermal_zone_device_exec(struct thermal_zone_device *tz,
+                             void (*cb)(struct thermal_zone_device *,
+                                        unsigned long),
+                             unsigned long data);
 
 struct thermal_cooling_device *thermal_cooling_device_register(const char *,
                void *, const struct thermal_cooling_device_ops *);
index 6a1e8f157255186249d1743c9951b4d9ab66eb35..4ee9d13749adc1ae0a6bd47136694c280ca943ae 100644 (file)
@@ -283,6 +283,7 @@ enum tpm_chip_flags {
        TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED    = BIT(6),
        TPM_CHIP_FLAG_FIRMWARE_UPGRADE          = BIT(7),
        TPM_CHIP_FLAG_SUSPENDED                 = BIT(8),
+       TPM_CHIP_FLAG_HWRNG_DISABLED            = BIT(9),
 };
 
 #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
index bdf8de2cdd935d31449b78e1b9c67fdcdc537bf2..7b4dd69555e497497460dcf5d72737fe5c09fd53 100644 (file)
@@ -155,6 +155,10 @@ retry:
                if (gso_type & SKB_GSO_UDP)
                        nh_off -= thlen;
 
+               /* Kernel has a special handling for GSO_BY_FRAGS. */
+               if (gso_size == GSO_BY_FRAGS)
+                       return -EINVAL;
+
                /* Too small packets are not really GSO ones. */
                if (skb->len - nh_off > gso_size) {
                        shinfo->gso_size = gso_size;
index 7c7d03aa9d0683a2988e3850af54669cb0f1c619..d6fa7c8767ad33f11926fbc2c1b80895cd7b4200 100644 (file)
@@ -562,6 +562,9 @@ ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband,
        if (WARN_ON(iftype >= NL80211_IFTYPE_MAX))
                return NULL;
 
+       if (iftype == NL80211_IFTYPE_AP_VLAN)
+               iftype = NL80211_IFTYPE_AP;
+
        for (i = 0; i < sband->n_iftype_data; i++)  {
                const struct ieee80211_sband_iftype_data *data =
                        &sband->iftype_data[i];
index 75efa6fb84413e79728ec0844cfe1d0c3858ac62..88644b3ca6600ca6fb1c06e9c9a896cd4e461309 100644 (file)
@@ -452,6 +452,49 @@ static inline void gro_normal_one(struct napi_struct *napi, struct sk_buff *skb,
                gro_normal_list(napi);
 }
 
+/* This function is the alternative of 'inet_iif' and 'inet_sdif'
+ * functions in case we can not rely on fields of IPCB.
+ *
+ * The caller must verify skb_valid_dst(skb) is false and skb->dev is initialized.
+ * The caller must hold the RCU read lock.
+ */
+static inline void inet_get_iif_sdif(const struct sk_buff *skb, int *iif, int *sdif)
+{
+       *iif = inet_iif(skb) ?: skb->dev->ifindex;
+       *sdif = 0;
+
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+       if (netif_is_l3_slave(skb->dev)) {
+               struct net_device *master = netdev_master_upper_dev_get_rcu(skb->dev);
+
+               *sdif = *iif;
+               *iif = master ? master->ifindex : 0;
+       }
+#endif
+}
+
+/* This function is the alternative of 'inet6_iif' and 'inet6_sdif'
+ * functions in case we can not rely on fields of IP6CB.
+ *
+ * The caller must verify skb_valid_dst(skb) is false and skb->dev is initialized.
+ * The caller must hold the RCU read lock.
+ */
+static inline void inet6_get_iif_sdif(const struct sk_buff *skb, int *iif, int *sdif)
+{
+       /* using skb->dev->ifindex because skb_dst(skb) is not initialized */
+       *iif = skb->dev->ifindex;
+       *sdif = 0;
+
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+       if (netif_is_l3_slave(skb->dev)) {
+               struct net_device *master = netdev_master_upper_dev_get_rcu(skb->dev);
+
+               *sdif = *iif;
+               *iif = master ? master->ifindex : 0;
+       }
+#endif
+}
+
 extern struct list_head offload_base;
 
 #endif /* _NET_IPV6_GRO_H */
index caa20a9055310f5ef108f9b1bb43214a3d598b9e..0bb32bfc61832dd787abcb2db3ee85d55c83f2c9 100644 (file)
@@ -107,11 +107,12 @@ static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
 
 static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb)
 {
-       if (!sk->sk_mark &&
-           READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept))
+       u32 mark = READ_ONCE(sk->sk_mark);
+
+       if (!mark && READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept))
                return skb->mark;
 
-       return sk->sk_mark;
+       return mark;
 }
 
 static inline int inet_request_bound_dev_if(const struct sock *sk,
index 50d435855ae252e55a6d5bec3bf42e9a5392558d..332521170d9b86ab8cf53e134e199d4312e298cf 100644 (file)
@@ -93,7 +93,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
 {
        ipcm_init(ipcm);
 
-       ipcm->sockc.mark = inet->sk.sk_mark;
+       ipcm->sockc.mark = READ_ONCE(inet->sk.sk_mark);
        ipcm->sockc.tsflags = inet->sk.sk_tsflags;
        ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
        ipcm->addr = inet->inet_saddr;
index 640441a2f92665867828fe774e8b2b6ce84467df..e9ae567c037dbf0e43e41c2c9126755123d83b73 100644 (file)
@@ -512,6 +512,7 @@ struct nft_set_elem_expr {
  *
  *     @list: table set list node
  *     @bindings: list of set bindings
+ *     @refs: internal refcounting for async set destruction
  *     @table: table this set belongs to
  *     @net: netnamespace this set belongs to
  *     @name: name of the set
@@ -533,6 +534,7 @@ struct nft_set_elem_expr {
  *     @expr: stateful expression
  *     @ops: set ops
  *     @flags: set flags
+ *     @dead: set will be freed, never cleared
  *     @genmask: generation mask
  *     @klen: key length
  *     @dlen: data length
@@ -541,6 +543,7 @@ struct nft_set_elem_expr {
 struct nft_set {
        struct list_head                list;
        struct list_head                bindings;
+       refcount_t                      refs;
        struct nft_table                *table;
        possible_net_t                  net;
        char                            *name;
@@ -562,7 +565,8 @@ struct nft_set {
        struct list_head                pending_update;
        /* runtime data below here */
        const struct nft_set_ops        *ops ____cacheline_aligned;
-       u16                             flags:14,
+       u16                             flags:13,
+                                       dead:1,
                                        genmask:2;
        u8                              klen;
        u8                              dlen;
@@ -596,7 +600,6 @@ struct nft_set *nft_set_lookup_global(const struct net *net,
 
 struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
                                            const struct nft_set *set);
-void *nft_set_catchall_gc(const struct nft_set *set);
 
 static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
 {
@@ -813,62 +816,6 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
 void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
                                const struct nft_set *set, void *elem);
 
-/**
- *     struct nft_set_gc_batch_head - nf_tables set garbage collection batch
- *
- *     @rcu: rcu head
- *     @set: set the elements belong to
- *     @cnt: count of elements
- */
-struct nft_set_gc_batch_head {
-       struct rcu_head                 rcu;
-       const struct nft_set            *set;
-       unsigned int                    cnt;
-};
-
-#define NFT_SET_GC_BATCH_SIZE  ((PAGE_SIZE -                             \
-                                 sizeof(struct nft_set_gc_batch_head)) / \
-                                sizeof(void *))
-
-/**
- *     struct nft_set_gc_batch - nf_tables set garbage collection batch
- *
- *     @head: GC batch head
- *     @elems: garbage collection elements
- */
-struct nft_set_gc_batch {
-       struct nft_set_gc_batch_head    head;
-       void                            *elems[NFT_SET_GC_BATCH_SIZE];
-};
-
-struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
-                                               gfp_t gfp);
-void nft_set_gc_batch_release(struct rcu_head *rcu);
-
-static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb)
-{
-       if (gcb != NULL)
-               call_rcu(&gcb->head.rcu, nft_set_gc_batch_release);
-}
-
-static inline struct nft_set_gc_batch *
-nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb,
-                      gfp_t gfp)
-{
-       if (gcb != NULL) {
-               if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems))
-                       return gcb;
-               nft_set_gc_batch_complete(gcb);
-       }
-       return nft_set_gc_batch_alloc(set, gfp);
-}
-
-static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
-                                       void *elem)
-{
-       gcb->elems[gcb->head.cnt++] = elem;
-}
-
 struct nft_expr_ops;
 /**
  *     struct nft_expr_type - nf_tables expression type
@@ -1557,39 +1504,30 @@ static inline void nft_set_elem_change_active(const struct net *net,
 
 #endif /* IS_ENABLED(CONFIG_NF_TABLES) */
 
-/*
- * We use a free bit in the genmask field to indicate the element
- * is busy, meaning it is currently being processed either by
- * the netlink API or GC.
- *
- * Even though the genmask is only a single byte wide, this works
- * because the extension structure if fully constant once initialized,
- * so there are no non-atomic write accesses unless it is already
- * marked busy.
- */
-#define NFT_SET_ELEM_BUSY_MASK (1 << 2)
+#define NFT_SET_ELEM_DEAD_MASK (1 << 2)
 
 #if defined(__LITTLE_ENDIAN_BITFIELD)
-#define NFT_SET_ELEM_BUSY_BIT  2
+#define NFT_SET_ELEM_DEAD_BIT  2
 #elif defined(__BIG_ENDIAN_BITFIELD)
-#define NFT_SET_ELEM_BUSY_BIT  (BITS_PER_LONG - BITS_PER_BYTE + 2)
+#define NFT_SET_ELEM_DEAD_BIT  (BITS_PER_LONG - BITS_PER_BYTE + 2)
 #else
 #error
 #endif
 
-static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext)
+static inline void nft_set_elem_dead(struct nft_set_ext *ext)
 {
        unsigned long *word = (unsigned long *)ext;
 
        BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
-       return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word);
+       set_bit(NFT_SET_ELEM_DEAD_BIT, word);
 }
 
-static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
+static inline int nft_set_elem_is_dead(const struct nft_set_ext *ext)
 {
        unsigned long *word = (unsigned long *)ext;
 
-       clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
+       BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
+       return test_bit(NFT_SET_ELEM_DEAD_BIT, word);
 }
 
 /**
@@ -1732,6 +1670,38 @@ struct nft_trans_flowtable {
 #define nft_trans_flowtable_flags(trans)       \
        (((struct nft_trans_flowtable *)trans->data)->flags)
 
+#define NFT_TRANS_GC_BATCHCOUNT        256
+
+struct nft_trans_gc {
+       struct list_head        list;
+       struct net              *net;
+       struct nft_set          *set;
+       u32                     seq;
+       u8                      count;
+       void                    *priv[NFT_TRANS_GC_BATCHCOUNT];
+       struct rcu_head         rcu;
+};
+
+struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
+                                       unsigned int gc_seq, gfp_t gfp);
+void nft_trans_gc_destroy(struct nft_trans_gc *trans);
+
+struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
+                                             unsigned int gc_seq, gfp_t gfp);
+void nft_trans_gc_queue_async_done(struct nft_trans_gc *gc);
+
+struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp);
+void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans);
+
+void nft_trans_gc_elem_add(struct nft_trans_gc *gc, void *priv);
+
+struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
+                                          unsigned int gc_seq);
+
+void nft_setelem_data_deactivate(const struct net *net,
+                                const struct nft_set *set,
+                                struct nft_set_elem *elem);
+
 int __init nft_chain_filter_init(void);
 void nft_chain_filter_fini(void);
 
@@ -1758,6 +1728,7 @@ struct nftables_pernet {
        struct mutex            commit_mutex;
        u64                     table_handle;
        unsigned int            base_seq;
+       unsigned int            gc_seq;
 };
 
 extern unsigned int nf_tables_net_id;
index 5a5c726472bd67656c6f66805f956ac99b5fc4ad..8c2a8e7d8f8e6737515efbfbdf1d14ec21ec5e5c 100644 (file)
@@ -168,7 +168,7 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi
                                                   __be16 dport, __be16 sport,
                                                   __u8 proto, __u8 tos, int oif)
 {
-       flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos,
+       flowi4_init_output(fl4, oif, sk ? READ_ONCE(sk->sk_mark) : 0, tos,
                           RT_SCOPE_UNIVERSE, proto,
                           sk ? inet_sk_flowi_flags(sk) : 0,
                           daddr, saddr, dport, sport, sock_net_uid(net, sk));
@@ -301,7 +301,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst,
        if (inet_sk(sk)->transparent)
                flow_flags |= FLOWI_FLAG_ANYSRC;
 
-       flowi4_init_output(fl4, oif, sk->sk_mark, ip_sock_rt_tos(sk),
+       flowi4_init_output(fl4, oif, READ_ONCE(sk->sk_mark), ip_sock_rt_tos(sk),
                           ip_sock_rt_scope(sk), protocol, flow_flags, dst,
                           src, dport, sport, sk->sk_uid);
 }
index 2eb916d1ff64866671a2197965eb857b47b810d9..e3d987b2ef124024110a0c67c4c4775742d3eb2d 100644 (file)
@@ -1420,6 +1420,12 @@ static inline bool sk_has_memory_pressure(const struct sock *sk)
        return sk->sk_prot->memory_pressure != NULL;
 }
 
+static inline bool sk_under_global_memory_pressure(const struct sock *sk)
+{
+       return sk->sk_prot->memory_pressure &&
+               !!*sk->sk_prot->memory_pressure;
+}
+
 static inline bool sk_under_memory_pressure(const struct sock *sk)
 {
        if (!sk->sk_prot->memory_pressure)
index 1648240c9668011aef9f10cc4ddbffdfe54712d3..6a9f8a5f387ceeb4e5652328d7ba05da129547c0 100644 (file)
@@ -556,12 +556,12 @@ static inline void vxlan_flag_attr_error(int attrtype,
 }
 
 static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh,
-                                           int hash,
+                                           u32 hash,
                                            struct vxlan_rdst *rdst)
 {
        struct fib_nh_common *nhc;
 
-       nhc = nexthop_path_fdb_result(nh, hash);
+       nhc = nexthop_path_fdb_result(nh, hash >> 1);
        if (unlikely(!nhc))
                return false;
 
index 151ca95dd08db32b7cf6db46ad441471dfffbc16..363c7d5105542ec7f43f91e5071b877314584bc5 100644 (file)
@@ -1984,6 +1984,7 @@ static inline void xfrm_dev_state_free(struct xfrm_state *x)
                if (dev->xfrmdev_ops->xdo_dev_state_free)
                        dev->xfrmdev_ops->xdo_dev_state_free(x);
                xso->dev = NULL;
+               xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
                netdev_put(dev, &xso->dev_tracker);
        }
 }
index 75b2235b99e217bad4b1c9b2bcae4a2c5b4940f9..b9230b6add041dbba870995974bffd4dc31f728b 100644 (file)
@@ -194,6 +194,7 @@ struct scsi_device {
        unsigned no_start_on_add:1;     /* do not issue start on add */
        unsigned allow_restart:1; /* issue START_UNIT in error handler */
        unsigned manage_start_stop:1;   /* Let HLD (sd) manage start/stop */
+       unsigned no_start_on_resume:1; /* Do not issue START_STOP_UNIT on resume */
        unsigned start_stop_pwr_cond:1; /* Set power cond. in START_STOP_UNIT */
        unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
        unsigned select_no_atn:1;
index fc3001483e6242cd2d2c9d726ae8d103fa0c879b..a5ef84944a0680690755599ae14469d9111513fa 100644 (file)
@@ -175,6 +175,9 @@ struct tegra_mc_icc_ops {
        int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak);
 };
 
+struct icc_node *tegra_mc_icc_xlate(struct of_phandle_args *spec, void *data);
+extern const struct tegra_mc_icc_ops tegra_mc_icc_ops;
+
 struct tegra_mc_ops {
        /*
         * @probe: Callback to set up SoC-specific bits of the memory controller. This is called
index bf06db8d2046c4a7f59070b724ce6fc7762f9d4b..7b1ddffa3dfc825f431bc575f4e86a3509dc9426 100644 (file)
@@ -381,6 +381,7 @@ TRACE_EVENT(tcp_cong_state_set,
                __field(const void *, skaddr)
                __field(__u16, sport)
                __field(__u16, dport)
+               __field(__u16, family)
                __array(__u8, saddr, 4)
                __array(__u8, daddr, 4)
                __array(__u8, saddr_v6, 16)
@@ -396,6 +397,7 @@ TRACE_EVENT(tcp_cong_state_set,
 
                __entry->sport = ntohs(inet->inet_sport);
                __entry->dport = ntohs(inet->inet_dport);
+               __entry->family = sk->sk_family;
 
                p32 = (__be32 *) __entry->saddr;
                *p32 = inet->inet_saddr;
@@ -409,7 +411,8 @@ TRACE_EVENT(tcp_cong_state_set,
                __entry->cong_state = ca_state;
        ),
 
-       TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c cong_state=%u",
+       TP_printk("family=%s sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c cong_state=%u",
+                 show_family_name(__entry->family),
                  __entry->sport, __entry->dport,
                  __entry->saddr, __entry->daddr,
                  __entry->saddr_v6, __entry->daddr_v6,
index 7865f5a9885b9bc12332448418cfef8214391f09..4f3932bb712dcd9d5b5b5eb2252efee784abc7e5 100644 (file)
@@ -710,9 +710,11 @@ enum {
        TCA_FLOWER_KEY_CFM_OPT_UNSPEC,
        TCA_FLOWER_KEY_CFM_MD_LEVEL,
        TCA_FLOWER_KEY_CFM_OPCODE,
-       TCA_FLOWER_KEY_CFM_OPT_MAX,
+       __TCA_FLOWER_KEY_CFM_OPT_MAX,
 };
 
+#define TCA_FLOWER_KEY_CFM_OPT_MAX (__TCA_FLOWER_KEY_CFM_OPT_MAX - 1)
+
 #define TCA_FLOWER_MASK_FLAGS_RANGE    (1 << 0) /* Range-based match */
 
 /* Match-all classifier */
index b958c2e9c9158b1dfd979ac87f7bdc1d48f94b8c..418eef6c55231b0567cf94112aefb790539497b3 100644 (file)
@@ -38,18 +38,6 @@ struct kyrofb_info {
        int wc_cookie;
 };
 
-extern int kyro_dev_init(void);
-extern void kyro_dev_reset(void);
-
-extern unsigned char *kyro_dev_physical_fb_ptr(void);
-extern unsigned char *kyro_dev_virtual_fb_ptr(void);
-extern void *kyro_dev_physical_regs_ptr(void);
-extern void *kyro_dev_virtual_regs_ptr(void);
-extern unsigned int kyro_dev_fb_size(void);
-extern unsigned int kyro_dev_regs_size(void);
-
-extern u32 kyro_dev_overlay_offset(void);
-
 /*
  * benedict.gaster@superh.com
  * Added the follow IOCTLS for the creation of overlay services...
index f4591b912ea8e966fd957d998f63811d70806a2b..93db3e4e7b68809f1d06b603c084d28bdd8a7a34 100644 (file)
@@ -3470,6 +3470,8 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp,
         * - use the kernel virtual address of the shared io_uring context
         *   (instead of the userspace-provided address, which has to be 0UL
         *   anyway).
+        * - use the same pgoff which the get_unmapped_area() uses to
+        *   calculate the page colouring.
         * For architectures without such aliasing requirements, the
         * architecture will return any suitable mapping because addr is 0.
         */
@@ -3478,6 +3480,7 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp,
        pgoff = 0;      /* has been translated to ptr above */
 #ifdef SHM_COLOUR
        addr = (uintptr_t) ptr;
+       pgoff = addr >> PAGE_SHIFT;
 #else
        addr = 0UL;
 #endif
index 10ca57f5bd249522755db6ce5baf28cc83aca8a7..e3fae26e025ddafada10394ee1780cd257d35ae8 100644 (file)
@@ -35,9 +35,11 @@ static bool io_openat_force_async(struct io_open *open)
 {
        /*
         * Don't bother trying for O_TRUNC, O_CREAT, or O_TMPFILE open,
-        * it'll always -EAGAIN
+        * it'll always -EAGAIN. Note that we test for __O_TMPFILE because
+        * O_TMPFILE includes O_DIRECTORY, which isn't a flag we need to force
+        * async for.
         */
-       return open->how.flags & (O_TRUNC | O_CREAT | O_TMPFILE);
+       return open->how.flags & (O_TRUNC | O_CREAT | __O_TMPFILE);
 }
 
 static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
index 6ae02be7a48e3165d860f29765b0f9f7e9443069..286ab3db0fde88ebf54a530683b78957eb3f9091 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/kthread.h>
+#include <linux/completion.h>
 #include <trace/events/xdp.h>
 #include <linux/btf_ids.h>
 
@@ -73,6 +74,7 @@ struct bpf_cpu_map_entry {
        struct rcu_head rcu;
 
        struct work_struct kthread_stop_wq;
+       struct completion kthread_running;
 };
 
 struct bpf_cpu_map {
@@ -129,11 +131,17 @@ static void __cpu_map_ring_cleanup(struct ptr_ring *ring)
         * invoked cpu_map_kthread_stop(). Catch any broken behaviour
         * gracefully and warn once.
         */
-       struct xdp_frame *xdpf;
+       void *ptr;
 
-       while ((xdpf = ptr_ring_consume(ring)))
-               if (WARN_ON_ONCE(xdpf))
-                       xdp_return_frame(xdpf);
+       while ((ptr = ptr_ring_consume(ring))) {
+               WARN_ON_ONCE(1);
+               if (unlikely(__ptr_test_bit(0, &ptr))) {
+                       __ptr_clear_bit(0, &ptr);
+                       kfree_skb(ptr);
+                       continue;
+               }
+               xdp_return_frame(ptr);
+       }
 }
 
 static void put_cpu_map_entry(struct bpf_cpu_map_entry *rcpu)
@@ -153,7 +161,6 @@ static void put_cpu_map_entry(struct bpf_cpu_map_entry *rcpu)
 static void cpu_map_kthread_stop(struct work_struct *work)
 {
        struct bpf_cpu_map_entry *rcpu;
-       int err;
 
        rcpu = container_of(work, struct bpf_cpu_map_entry, kthread_stop_wq);
 
@@ -163,14 +170,7 @@ static void cpu_map_kthread_stop(struct work_struct *work)
        rcu_barrier();
 
        /* kthread_stop will wake_up_process and wait for it to complete */
-       err = kthread_stop(rcpu->kthread);
-       if (err) {
-               /* kthread_stop may be called before cpu_map_kthread_run
-                * is executed, so we need to release the memory related
-                * to rcpu.
-                */
-               put_cpu_map_entry(rcpu);
-       }
+       kthread_stop(rcpu->kthread);
 }
 
 static void cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu,
@@ -298,11 +298,11 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
        return nframes;
 }
 
-
 static int cpu_map_kthread_run(void *data)
 {
        struct bpf_cpu_map_entry *rcpu = data;
 
+       complete(&rcpu->kthread_running);
        set_current_state(TASK_INTERRUPTIBLE);
 
        /* When kthread gives stop order, then rcpu have been disconnected
@@ -467,6 +467,7 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value,
                goto free_ptr_ring;
 
        /* Setup kthread */
+       init_completion(&rcpu->kthread_running);
        rcpu->kthread = kthread_create_on_node(cpu_map_kthread_run, rcpu, numa,
                                               "cpumap/%d/map:%d", cpu,
                                               map->id);
@@ -480,6 +481,12 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value,
        kthread_bind(rcpu->kthread, cpu);
        wake_up_process(rcpu->kthread);
 
+       /* Make sure kthread has been running, so kthread_stop() will not
+        * stop the kthread prematurely and all pending frames or skbs
+        * will be handled by the kthread before kthread_stop() returns.
+        */
+       wait_for_completion(&rcpu->kthread_running);
+
        return rcpu;
 
 free_prog:
index e1b4bfa938ddf8daa4610727d74ef23364a4b463..2b4a946a6ff5cfcae69fd9e03ee1d5cc0728736e 100644 (file)
@@ -1166,7 +1166,7 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
        int error;
 
        if (!hibernation_available())
-               return 0;
+               return n;
 
        if (len && buf[len-1] == '\n')
                len--;
index 5f2dcabad202c976b1005599a37b87fd0231ce12..bd1a42b23f3ffdbfecda45a67954de037ada2cf5 100644 (file)
@@ -661,8 +661,7 @@ static DEFINE_PER_CPU(int, bpf_trace_nest_level);
 BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
           u64, flags, void *, data, u64, size)
 {
-       struct bpf_trace_sample_data *sds = this_cpu_ptr(&bpf_trace_sds);
-       int nest_level = this_cpu_inc_return(bpf_trace_nest_level);
+       struct bpf_trace_sample_data *sds;
        struct perf_raw_record raw = {
                .frag = {
                        .size = size,
@@ -670,7 +669,11 @@ BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
                },
        };
        struct perf_sample_data *sd;
-       int err;
+       int nest_level, err;
+
+       preempt_disable();
+       sds = this_cpu_ptr(&bpf_trace_sds);
+       nest_level = this_cpu_inc_return(bpf_trace_nest_level);
 
        if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(sds->sds))) {
                err = -EBUSY;
@@ -688,9 +691,9 @@ BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
        perf_sample_save_raw_data(sd, &raw);
 
        err = __bpf_perf_event_output(regs, map, flags, sd);
-
 out:
        this_cpu_dec(bpf_trace_nest_level);
+       preempt_enable();
        return err;
 }
 
@@ -715,7 +718,6 @@ static DEFINE_PER_CPU(struct bpf_trace_sample_data, bpf_misc_sds);
 u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
                     void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy)
 {
-       int nest_level = this_cpu_inc_return(bpf_event_output_nest_level);
        struct perf_raw_frag frag = {
                .copy           = ctx_copy,
                .size           = ctx_size,
@@ -732,8 +734,12 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
        };
        struct perf_sample_data *sd;
        struct pt_regs *regs;
+       int nest_level;
        u64 ret;
 
+       preempt_disable();
+       nest_level = this_cpu_inc_return(bpf_event_output_nest_level);
+
        if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(bpf_misc_sds.sds))) {
                ret = -EBUSY;
                goto out;
@@ -748,6 +754,7 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
        ret = __bpf_perf_event_output(regs, map, flags, sd);
 out:
        this_cpu_dec(bpf_event_output_nest_level);
+       preempt_enable();
        return ret;
 }
 
index 02a8f402eeb543ef28367b1d722997aebf45e7b1..800b4208dba9a0ebf0a748f40b8366edc86f6a29 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/sched/debug.h>
 #include <linux/nmi.h>
 #include <linux/kvm_para.h>
+#include <linux/delay.h>
 
 #include "workqueue_internal.h"
 
@@ -338,8 +339,10 @@ static cpumask_var_t *wq_numa_possible_cpumask;
  * Per-cpu work items which run for longer than the following threshold are
  * automatically considered CPU intensive and excluded from concurrency
  * management to prevent them from noticeably delaying other per-cpu work items.
+ * ULONG_MAX indicates that the user hasn't overridden it with a boot parameter.
+ * The actual value is initialized in wq_cpu_intensive_thresh_init().
  */
-static unsigned long wq_cpu_intensive_thresh_us = 10000;
+static unsigned long wq_cpu_intensive_thresh_us = ULONG_MAX;
 module_param_named(cpu_intensive_thresh_us, wq_cpu_intensive_thresh_us, ulong, 0644);
 
 static bool wq_disable_numa;
@@ -6513,6 +6516,42 @@ void __init workqueue_init_early(void)
               !system_freezable_power_efficient_wq);
 }
 
+static void __init wq_cpu_intensive_thresh_init(void)
+{
+       unsigned long thresh;
+       unsigned long bogo;
+
+       /* if the user set it to a specific value, keep it */
+       if (wq_cpu_intensive_thresh_us != ULONG_MAX)
+               return;
+
+       /*
+        * The default of 10ms is derived from the fact that most modern (as of
+        * 2023) processors can do a lot in 10ms and that it's just below what
+        * most consider human-perceivable. However, the kernel also runs on a
+        * lot slower CPUs including microcontrollers where the threshold is way
+        * too low.
+        *
+        * Let's scale up the threshold upto 1 second if BogoMips is below 4000.
+        * This is by no means accurate but it doesn't have to be. The mechanism
+        * is still useful even when the threshold is fully scaled up. Also, as
+        * the reports would usually be applicable to everyone, some machines
+        * operating on longer thresholds won't significantly diminish their
+        * usefulness.
+        */
+       thresh = 10 * USEC_PER_MSEC;
+
+       /* see init/calibrate.c for lpj -> BogoMIPS calculation */
+       bogo = max_t(unsigned long, loops_per_jiffy / 500000 * HZ, 1);
+       if (bogo < 4000)
+               thresh = min_t(unsigned long, thresh * 4000 / bogo, USEC_PER_SEC);
+
+       pr_debug("wq_cpu_intensive_thresh: lpj=%lu BogoMIPS=%lu thresh_us=%lu\n",
+                loops_per_jiffy, bogo, thresh);
+
+       wq_cpu_intensive_thresh_us = thresh;
+}
+
 /**
  * workqueue_init - bring workqueue subsystem fully online
  *
@@ -6528,6 +6567,8 @@ void __init workqueue_init(void)
        struct worker_pool *pool;
        int cpu, bkt;
 
+       wq_cpu_intensive_thresh_init();
+
        /*
         * It'd be simpler to initialize NUMA in workqueue_init_early() but
         * CPU to node mapping may not be available that early on some
index fbc89baf7de645c12f137ba488acf16963e9f249..d6798513a8c21fe7007e34a64977a7a499d09fb4 100644 (file)
@@ -1200,7 +1200,7 @@ config WQ_CPU_INTENSIVE_REPORT
        help
          Say Y here to enable reporting of concurrency-managed per-cpu work
          items that hog CPUs for longer than
-         workqueue.cpu_intensive_threshold_us. Workqueue automatically
+         workqueue.cpu_intensive_thresh_us. Workqueue automatically
          detects and excludes them from concurrency management to prevent
          them from stalling other per-cpu work items. Occassional
          triggering may not necessarily indicate a problem. Repeated
index 42d307ade225ea639612093a3438105e8946c96c..1ffae65bb7eed6531de943c1a476d870804b5756 100644 (file)
@@ -82,7 +82,13 @@ obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
 obj-$(CONFIG_TEST_DYNAMIC_DEBUG) += test_dynamic_debug.o
 obj-$(CONFIG_TEST_PRINTF) += test_printf.o
 obj-$(CONFIG_TEST_SCANF) += test_scanf.o
+
 obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
+ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_KASAN),yy)
+# FIXME: Clang breaks test_bitmap_const_eval when KASAN and GCOV are enabled
+GCOV_PROFILE_test_bitmap.o := n
+endif
+
 obj-$(CONFIG_TEST_UUID) += test_uuid.o
 obj-$(CONFIG_TEST_XARRAY) += test_xarray.o
 obj-$(CONFIG_TEST_MAPLE_TREE) += test_maple_tree.o
index de356f16773a04c63a5ef3a090ec5e3ec7321701..a7fd02b5ae264ce1d8e58b949face2bbefc5fcb0 100644 (file)
@@ -45,6 +45,7 @@ EXPORT_SYMBOL(cpumask_next_wrap);
  * alloc_cpumask_var_node - allocate a struct cpumask on a given node
  * @mask: pointer to cpumask_var_t where the cpumask is returned
  * @flags: GFP_ flags
+ * @node: memory node from which to allocate or %NUMA_NO_NODE
  *
  * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is
  * a nop returning a constant 1 (in <linux/cpumask.h>)
@@ -157,7 +158,9 @@ EXPORT_SYMBOL(cpumask_local_spread);
 static DEFINE_PER_CPU(int, distribute_cpu_mask_prev);
 
 /**
- * cpumask_any_and_distribute - Return an arbitrary cpu within srcp1 & srcp2.
+ * cpumask_any_and_distribute - Return an arbitrary cpu within src1p & src2p.
+ * @src1p: first &cpumask for intersection
+ * @src2p: second &cpumask for intersection
  *
  * Iterated calls using the same srcp1 and srcp2 will be distributed within
  * their intersection.
index e86231a44c3de53e62d82977186e0b509ebf428b..c65566b4dc662afff966b773b78631de185c8851 100644 (file)
@@ -1148,7 +1148,7 @@ static ssize_t extract_user_to_sg(struct iov_iter *iter,
 
 failed:
        while (sgtable->nents > sgtable->orig_nents)
-               put_page(sg_page(&sgtable->sgl[--sgtable->nents]));
+               unpin_user_page(sg_page(&sgtable->sgl[--sgtable->nents]));
        return res;
 }
 
index 187f5b2db4cf1685d62bbf7cf6f18dcefbcf40a0..f2ea9f30c7c5d7764a52fc1f24c37393fb3bbb2a 100644 (file)
@@ -1161,6 +1161,10 @@ static void __init test_bitmap_print_buf(void)
        }
 }
 
+/*
+ * FIXME: Clang breaks compile-time evaluations when KASAN and GCOV are enabled.
+ * To workaround it, GCOV is force-disabled in Makefile for this configuration.
+ */
 static void __init test_bitmap_const_eval(void)
 {
        DECLARE_BITMAP(bitmap, BITS_PER_LONG);
@@ -1186,11 +1190,7 @@ static void __init test_bitmap_const_eval(void)
         * the compiler is fixed.
         */
        bitmap_clear(bitmap, 0, BITS_PER_LONG);
-#if defined(__s390__) && defined(__clang__)
-       if (!const_test_bit(7, bitmap))
-#else
        if (!test_bit(7, bitmap))
-#endif
                bitmap_set(bitmap, 5, 2);
 
        /* Equals to `unsigned long bitopvar = BIT(20)` */
index dbc9f86b19343f9ff79f3a237f5bd5ec58a5e863..eacca2794e47081fb5ef2ab12e3c98dc335e0dbd 100644 (file)
@@ -912,11 +912,12 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
 
                /*
                 * Check if the pageblock has already been marked skipped.
-                * Only the aligned PFN is checked as the caller isolates
+                * Only the first PFN is checked as the caller isolates
                 * COMPACT_CLUSTER_MAX at a time so the second call must
                 * not falsely conclude that the block should be skipped.
                 */
-               if (!valid_page && pageblock_aligned(low_pfn)) {
+               if (!valid_page && (pageblock_aligned(low_pfn) ||
+                                   low_pfn == cc->zone->zone_start_pfn)) {
                        if (!isolation_suitable(cc, page)) {
                                low_pfn = end_pfn;
                                folio = NULL;
@@ -2002,7 +2003,8 @@ static isolate_migrate_t isolate_migratepages(struct compact_control *cc)
                 * before making it "skip" so other compaction instances do
                 * not scan the same block.
                 */
-               if (pageblock_aligned(low_pfn) &&
+               if ((pageblock_aligned(low_pfn) ||
+                    low_pfn == cc->zone->zone_start_pfn) &&
                    !fast_find_block && !isolation_suitable(cc, page))
                        continue;
 
index 91cff7f2997efec5c0108c17f6864cd907db447a..eb9580942a5c320298fb1c49efc3173b61f766d7 100644 (file)
@@ -273,6 +273,7 @@ struct damos_filter *damos_new_filter(enum damos_filter_type type,
                return NULL;
        filter->type = type;
        filter->matching = matching;
+       INIT_LIST_HEAD(&filter->list);
        return filter;
 }
 
index 64a3239b6407e9e3bdcf26d49386a779142ff006..6da626bfb52e3f21c36ef7b194d4f03132abf013 100644 (file)
@@ -1579,9 +1579,37 @@ static inline void destroy_compound_gigantic_folio(struct folio *folio,
                                                unsigned int order) { }
 #endif
 
+static inline void __clear_hugetlb_destructor(struct hstate *h,
+                                               struct folio *folio)
+{
+       lockdep_assert_held(&hugetlb_lock);
+
+       /*
+        * Very subtle
+        *
+        * For non-gigantic pages set the destructor to the normal compound
+        * page dtor.  This is needed in case someone takes an additional
+        * temporary ref to the page, and freeing is delayed until they drop
+        * their reference.
+        *
+        * For gigantic pages set the destructor to the null dtor.  This
+        * destructor will never be called.  Before freeing the gigantic
+        * page destroy_compound_gigantic_folio will turn the folio into a
+        * simple group of pages.  After this the destructor does not
+        * apply.
+        *
+        */
+       if (hstate_is_gigantic(h))
+               folio_set_compound_dtor(folio, NULL_COMPOUND_DTOR);
+       else
+               folio_set_compound_dtor(folio, COMPOUND_PAGE_DTOR);
+}
+
 /*
- * Remove hugetlb folio from lists, and update dtor so that the folio appears
- * as just a compound page.
+ * Remove hugetlb folio from lists.
+ * If vmemmap exists for the folio, update dtor so that the folio appears
+ * as just a compound page.  Otherwise, wait until after allocating vmemmap
+ * to update dtor.
  *
  * A reference is held on the folio, except in the case of demote.
  *
@@ -1612,31 +1640,19 @@ static void __remove_hugetlb_folio(struct hstate *h, struct folio *folio,
        }
 
        /*
-        * Very subtle
-        *
-        * For non-gigantic pages set the destructor to the normal compound
-        * page dtor.  This is needed in case someone takes an additional
-        * temporary ref to the page, and freeing is delayed until they drop
-        * their reference.
-        *
-        * For gigantic pages set the destructor to the null dtor.  This
-        * destructor will never be called.  Before freeing the gigantic
-        * page destroy_compound_gigantic_folio will turn the folio into a
-        * simple group of pages.  After this the destructor does not
-        * apply.
-        *
-        * This handles the case where more than one ref is held when and
-        * after update_and_free_hugetlb_folio is called.
-        *
-        * In the case of demote we do not ref count the page as it will soon
-        * be turned into a page of smaller size.
+        * We can only clear the hugetlb destructor after allocating vmemmap
+        * pages.  Otherwise, someone (memory error handling) may try to write
+        * to tail struct pages.
+        */
+       if (!folio_test_hugetlb_vmemmap_optimized(folio))
+               __clear_hugetlb_destructor(h, folio);
+
+        /*
+         * In the case of demote we do not ref count the page as it will soon
+         * be turned into a page of smaller size.
         */
        if (!demote)
                folio_ref_unfreeze(folio, 1);
-       if (hstate_is_gigantic(h))
-               folio_set_compound_dtor(folio, NULL_COMPOUND_DTOR);
-       else
-               folio_set_compound_dtor(folio, COMPOUND_PAGE_DTOR);
 
        h->nr_huge_pages--;
        h->nr_huge_pages_node[nid]--;
@@ -1705,6 +1721,7 @@ static void __update_and_free_hugetlb_folio(struct hstate *h,
 {
        int i;
        struct page *subpage;
+       bool clear_dtor = folio_test_hugetlb_vmemmap_optimized(folio);
 
        if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported())
                return;
@@ -1735,6 +1752,16 @@ static void __update_and_free_hugetlb_folio(struct hstate *h,
        if (unlikely(folio_test_hwpoison(folio)))
                folio_clear_hugetlb_hwpoison(folio);
 
+       /*
+        * If vmemmap pages were allocated above, then we need to clear the
+        * hugetlb destructor under the hugetlb lock.
+        */
+       if (clear_dtor) {
+               spin_lock_irq(&hugetlb_lock);
+               __clear_hugetlb_destructor(h, folio);
+               spin_unlock_irq(&hugetlb_lock);
+       }
+
        for (i = 0; i < pages_per_huge_page(h); i++) {
                subpage = folio_page(folio, i);
                subpage->flags &= ~(1 << PG_locked | 1 << PG_error |
index ba266359da55f1f0f8cfa82fccffad5fbd5d5de3..d20d7662419beadd6133cb1df445f9e41a03287b 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -2784,6 +2784,8 @@ struct page *ksm_might_need_to_copy(struct page *page,
                        anon_vma->root == vma->anon_vma->root) {
                return page;            /* still no need to copy it */
        }
+       if (PageHWPoison(page))
+               return ERR_PTR(-EHWPOISON);
        if (!PageUptodate(page))
                return page;            /* let do_swap_page report the error */
 
index ece5d481b5fff923aba2a710aeae1d8dd2539467..9a285038d7658cbfda1ade9c55c6c96502f258fb 100644 (file)
@@ -2466,7 +2466,7 @@ int unpoison_memory(unsigned long pfn)
 {
        struct folio *folio;
        struct page *p;
-       int ret = -EBUSY;
+       int ret = -EBUSY, ghp;
        unsigned long count = 1;
        bool huge = false;
        static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL,
@@ -2499,6 +2499,13 @@ int unpoison_memory(unsigned long pfn)
                goto unlock_mutex;
        }
 
+       if (folio_test_slab(folio) || PageTable(&folio->page) || folio_test_reserved(folio))
+               goto unlock_mutex;
+
+       /*
+        * Note that folio->_mapcount is overloaded in SLAB, so the simple test
+        * in folio_mapped() has to be done after folio_test_slab() is checked.
+        */
        if (folio_mapped(folio)) {
                unpoison_pr_info("Unpoison: Someone maps the hwpoison page %#lx\n",
                                 pfn, &unpoison_rs);
@@ -2511,32 +2518,28 @@ int unpoison_memory(unsigned long pfn)
                goto unlock_mutex;
        }
 
-       if (folio_test_slab(folio) || PageTable(&folio->page) || folio_test_reserved(folio))
-               goto unlock_mutex;
-
-       ret = get_hwpoison_page(p, MF_UNPOISON);
-       if (!ret) {
+       ghp = get_hwpoison_page(p, MF_UNPOISON);
+       if (!ghp) {
                if (PageHuge(p)) {
                        huge = true;
                        count = folio_free_raw_hwp(folio, false);
-                       if (count == 0) {
-                               ret = -EBUSY;
+                       if (count == 0)
                                goto unlock_mutex;
-                       }
                }
                ret = folio_test_clear_hwpoison(folio) ? 0 : -EBUSY;
-       } else if (ret < 0) {
-               if (ret == -EHWPOISON) {
+       } else if (ghp < 0) {
+               if (ghp == -EHWPOISON) {
                        ret = put_page_back_buddy(p) ? 0 : -EBUSY;
-               } else
+               } else {
+                       ret = ghp;
                        unpoison_pr_info("Unpoison: failed to grab page %#lx\n",
                                         pfn, &unpoison_rs);
+               }
        } else {
                if (PageHuge(p)) {
                        huge = true;
                        count = folio_free_raw_hwp(folio, false);
                        if (count == 0) {
-                               ret = -EBUSY;
                                folio_put(folio);
                                goto unlock_mutex;
                        }
index 603b2f419948319fec35ea818adf516aca7ae4aa..cdc4d4c1c858a957c9731193eb06c2d0bb8ca74e 100644 (file)
@@ -5257,11 +5257,8 @@ EXPORT_SYMBOL_GPL(handle_mm_fault);
 
 static inline bool get_mmap_lock_carefully(struct mm_struct *mm, struct pt_regs *regs)
 {
-       /* Even if this succeeds, make it clear we *might* have slept */
-       if (likely(mmap_read_trylock(mm))) {
-               might_sleep();
+       if (likely(mmap_read_trylock(mm)))
                return true;
-       }
 
        if (regs && !user_mode(regs)) {
                unsigned long ip = instruction_pointer(regs);
@@ -5705,6 +5702,9 @@ int __access_remote_vm(struct mm_struct *mm, unsigned long addr, void *buf,
        if (mmap_read_lock_killable(mm))
                return 0;
 
+       /* Untag the address before looking up the VMA */
+       addr = untagged_addr_remote(mm, addr);
+
        /* Avoid triggering the temporary warning in __get_user_pages */
        if (!vma_lookup(mm, addr) && !expand_stack(mm, addr))
                return 0;
index 8e6dde68b38904a97f6b30fbda4ffbe1122c7837..b15112b1f1a8bceea5872b5e333b4fcac76b2901 100644 (file)
@@ -1746,7 +1746,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
        struct page *swapcache;
        spinlock_t *ptl;
        pte_t *pte, new_pte, old_pte;
-       bool hwposioned = false;
+       bool hwpoisoned = PageHWPoison(page);
        int ret = 1;
 
        swapcache = page;
@@ -1754,7 +1754,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
        if (unlikely(!page))
                return -ENOMEM;
        else if (unlikely(PTR_ERR(page) == -EHWPOISON))
-               hwposioned = true;
+               hwpoisoned = true;
 
        pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
        if (unlikely(!pte || !pte_same_as_swp(ptep_get(pte),
@@ -1765,11 +1765,11 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
 
        old_pte = ptep_get(pte);
 
-       if (unlikely(hwposioned || !PageUptodate(page))) {
+       if (unlikely(hwpoisoned || !PageUptodate(page))) {
                swp_entry_t swp_entry;
 
                dec_mm_counter(vma->vm_mm, MM_SWAPENTS);
-               if (hwposioned) {
+               if (hwpoisoned) {
                        swp_entry = make_hwpoison_entry(swapcache);
                        page = swapcache;
                } else {
index 3f057970504e3b061242b9f2de65c42357fea5f4..32916d28d9d968aea3a653eeb4c9fa86a0f89448 100644 (file)
@@ -1798,6 +1798,7 @@ static void replace_sub_page(struct size_class *class, struct zspage *zspage,
 
 static bool zs_page_isolate(struct page *page, isolate_mode_t mode)
 {
+       struct zs_pool *pool;
        struct zspage *zspage;
 
        /*
@@ -1807,9 +1808,10 @@ static bool zs_page_isolate(struct page *page, isolate_mode_t mode)
        VM_BUG_ON_PAGE(PageIsolated(page), page);
 
        zspage = get_zspage(page);
-       migrate_write_lock(zspage);
+       pool = zspage->pool;
+       spin_lock(&pool->lock);
        inc_zspage_isolation(zspage);
-       migrate_write_unlock(zspage);
+       spin_unlock(&pool->lock);
 
        return true;
 }
@@ -1875,12 +1877,12 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
        kunmap_atomic(s_addr);
 
        replace_sub_page(class, zspage, newpage, page);
+       dec_zspage_isolation(zspage);
        /*
         * Since we complete the data copy and set up new zspage structure,
         * it's okay to release the pool's lock.
         */
        spin_unlock(&pool->lock);
-       dec_zspage_isolation(zspage);
        migrate_write_unlock(zspage);
 
        get_page(newpage);
@@ -1897,14 +1899,16 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
 
 static void zs_page_putback(struct page *page)
 {
+       struct zs_pool *pool;
        struct zspage *zspage;
 
        VM_BUG_ON_PAGE(!PageIsolated(page), page);
 
        zspage = get_zspage(page);
-       migrate_write_lock(zspage);
+       pool = zspage->pool;
+       spin_lock(&pool->lock);
        dec_zspage_isolation(zspage);
-       migrate_write_unlock(zspage);
+       spin_unlock(&pool->lock);
 }
 
 static const struct movable_operations zsmalloc_mops = {
index ba6b52b1d7767fdd7b57d1b8e5519495340c572c..e10f59375659f8342ff7e2d6da834920fd526184 100644 (file)
@@ -865,7 +865,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 
        skb->dev = dev;
        skb->priority = sk->sk_priority;
-       skb->mark = sk->sk_mark;
+       skb->mark = READ_ONCE(sk->sk_mark);
        skb->tstamp = sockc.transmit_time;
 
        skb_setup_tx_timestamp(skb, sockc.tsflags);
index 11c04e7d928eb1fd14bbab519f307eee349eca28..658a6f2320cfa17721a6bc395a278729506aef6d 100644 (file)
@@ -3334,17 +3334,24 @@ static int linger_reg_commit_wait(struct ceph_osd_linger_request *lreq)
        int ret;
 
        dout("%s lreq %p linger_id %llu\n", __func__, lreq, lreq->linger_id);
-       ret = wait_for_completion_interruptible(&lreq->reg_commit_wait);
+       ret = wait_for_completion_killable(&lreq->reg_commit_wait);
        return ret ?: lreq->reg_commit_error;
 }
 
-static int linger_notify_finish_wait(struct ceph_osd_linger_request *lreq)
+static int linger_notify_finish_wait(struct ceph_osd_linger_request *lreq,
+                                    unsigned long timeout)
 {
-       int ret;
+       long left;
 
        dout("%s lreq %p linger_id %llu\n", __func__, lreq, lreq->linger_id);
-       ret = wait_for_completion_interruptible(&lreq->notify_finish_wait);
-       return ret ?: lreq->notify_finish_error;
+       left = wait_for_completion_killable_timeout(&lreq->notify_finish_wait,
+                                               ceph_timeout_jiffies(timeout));
+       if (left <= 0)
+               left = left ?: -ETIMEDOUT;
+       else
+               left = lreq->notify_finish_error; /* completed */
+
+       return left;
 }
 
 /*
@@ -4896,7 +4903,8 @@ int ceph_osdc_notify(struct ceph_osd_client *osdc,
        linger_submit(lreq);
        ret = linger_reg_commit_wait(lreq);
        if (!ret)
-               ret = linger_notify_finish_wait(lreq);
+               ret = linger_notify_finish_wait(lreq,
+                                msecs_to_jiffies(2 * timeout * MSEC_PER_SEC));
        else
                dout("lreq %p failed to initiate notify %d\n", lreq, ret);
 
index d4172534dfa8dc7e09728d8224b7962999dac8c9..cca7594be92ec6f84cf67992b2deca74f311670f 100644 (file)
@@ -496,8 +496,11 @@ bpf_sk_storage_diag_alloc(const struct nlattr *nla_stgs)
                return ERR_PTR(-EPERM);
 
        nla_for_each_nested(nla, nla_stgs, rem) {
-               if (nla_type(nla) == SK_DIAG_BPF_STORAGE_REQ_MAP_FD)
+               if (nla_type(nla) == SK_DIAG_BPF_STORAGE_REQ_MAP_FD) {
+                       if (nla_len(nla) != sizeof(u32))
+                               return ERR_PTR(-EINVAL);
                        nr_maps++;
+               }
        }
 
        diag = kzalloc(struct_size(diag, maps, nr_maps), GFP_KERNEL);
index 06ba0e56e3693e22dc5bd32acb0d74c4165d84f6..28a59596987a9e55d1ad936a880e2b1981c04ca0 100644 (file)
@@ -4116,12 +4116,6 @@ BPF_CALL_2(bpf_xdp_adjust_tail, struct xdp_buff *, xdp, int, offset)
        if (unlikely(data_end > data_hard_end))
                return -EINVAL;
 
-       /* ALL drivers MUST init xdp->frame_sz, chicken check below */
-       if (unlikely(xdp->frame_sz > PAGE_SIZE)) {
-               WARN_ONCE(1, "Too BIG xdp->frame_sz = %d\n", xdp->frame_sz);
-               return -EINVAL;
-       }
-
        if (unlikely(data_end < xdp->data + ETH_HLEN))
                return -EINVAL;
 
index 3ad4e030846d8d9629bc1482dac57f862c844f84..aef25aa5cf1dd49b467b760624f640d650d0f8d2 100644 (file)
@@ -5140,13 +5140,17 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
        br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
        if (br_spec) {
                nla_for_each_nested(attr, br_spec, rem) {
-                       if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
+                       if (nla_type(attr) == IFLA_BRIDGE_FLAGS && !have_flags) {
                                if (nla_len(attr) < sizeof(flags))
                                        return -EINVAL;
 
                                have_flags = true;
                                flags = nla_get_u16(attr);
-                               break;
+                       }
+
+                       if (nla_type(attr) == IFLA_BRIDGE_MODE) {
+                               if (nla_len(attr) < sizeof(u16))
+                                       return -EINVAL;
                        }
                }
        }
index a29508e1ff3568583263b9307f7b1a0e814ba76d..ef1a2eb6520bf4fc855dc86c8957ffb5bdcd5878 100644 (file)
@@ -1120,13 +1120,19 @@ static void sk_psock_strp_data_ready(struct sock *sk)
 
 int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)
 {
+       int ret;
+
        static const struct strp_callbacks cb = {
                .rcv_msg        = sk_psock_strp_read,
                .read_sock_done = sk_psock_strp_read_done,
                .parse_msg      = sk_psock_strp_parse,
        };
 
-       return strp_init(&psock->strp, sk, &cb);
+       ret = strp_init(&psock->strp, sk, &cb);
+       if (!ret)
+               sk_psock_set_state(psock, SK_PSOCK_RX_STRP_ENABLED);
+
+       return ret;
 }
 
 void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)
@@ -1154,7 +1160,7 @@ void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock)
 static void sk_psock_done_strp(struct sk_psock *psock)
 {
        /* Parser has been stopped */
-       if (psock->progs.stream_parser)
+       if (sk_psock_test_state(psock, SK_PSOCK_RX_STRP_ENABLED))
                strp_done(&psock->strp);
 }
 #else
index 9370fd50aa2c9d84b86651433c0df338a1518547..c9cffb7acbeae02c656a00760bda09090014abef 100644 (file)
@@ -429,6 +429,7 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen,
 {
        struct __kernel_sock_timeval tv;
        int err = sock_copy_user_timeval(&tv, optval, optlen, old_timeval);
+       long val;
 
        if (err)
                return err;
@@ -439,7 +440,7 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen,
        if (tv.tv_sec < 0) {
                static int warned __read_mostly;
 
-               *timeo_p = 0;
+               WRITE_ONCE(*timeo_p, 0);
                if (warned < 10 && net_ratelimit()) {
                        warned++;
                        pr_info("%s: `%s' (pid %d) tries to set negative timeout\n",
@@ -447,11 +448,12 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen,
                }
                return 0;
        }
-       *timeo_p = MAX_SCHEDULE_TIMEOUT;
-       if (tv.tv_sec == 0 && tv.tv_usec == 0)
-               return 0;
-       if (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1))
-               *timeo_p = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec, USEC_PER_SEC / HZ);
+       val = MAX_SCHEDULE_TIMEOUT;
+       if ((tv.tv_sec || tv.tv_usec) &&
+           (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1)))
+               val = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec,
+                                                   USEC_PER_SEC / HZ);
+       WRITE_ONCE(*timeo_p, val);
        return 0;
 }
 
@@ -804,7 +806,7 @@ EXPORT_SYMBOL(sock_no_linger);
 void sock_set_priority(struct sock *sk, u32 priority)
 {
        lock_sock(sk);
-       sk->sk_priority = priority;
+       WRITE_ONCE(sk->sk_priority, priority);
        release_sock(sk);
 }
 EXPORT_SYMBOL(sock_set_priority);
@@ -813,9 +815,9 @@ void sock_set_sndtimeo(struct sock *sk, s64 secs)
 {
        lock_sock(sk);
        if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1)
-               sk->sk_sndtimeo = secs * HZ;
+               WRITE_ONCE(sk->sk_sndtimeo, secs * HZ);
        else
-               sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+               WRITE_ONCE(sk->sk_sndtimeo, MAX_SCHEDULE_TIMEOUT);
        release_sock(sk);
 }
 EXPORT_SYMBOL(sock_set_sndtimeo);
@@ -988,7 +990,7 @@ EXPORT_SYMBOL(sock_set_rcvbuf);
 static void __sock_set_mark(struct sock *sk, u32 val)
 {
        if (val != sk->sk_mark) {
-               sk->sk_mark = val;
+               WRITE_ONCE(sk->sk_mark, val);
                sk_dst_reset(sk);
        }
 }
@@ -1007,7 +1009,7 @@ static void sock_release_reserved_memory(struct sock *sk, int bytes)
        bytes = round_down(bytes, PAGE_SIZE);
 
        WARN_ON(bytes > sk->sk_reserved_mem);
-       sk->sk_reserved_mem -= bytes;
+       WRITE_ONCE(sk->sk_reserved_mem, sk->sk_reserved_mem - bytes);
        sk_mem_reclaim(sk);
 }
 
@@ -1044,7 +1046,8 @@ static int sock_reserve_memory(struct sock *sk, int bytes)
        }
        sk->sk_forward_alloc += pages << PAGE_SHIFT;
 
-       sk->sk_reserved_mem += pages << PAGE_SHIFT;
+       WRITE_ONCE(sk->sk_reserved_mem,
+                  sk->sk_reserved_mem + (pages << PAGE_SHIFT));
 
        return 0;
 }
@@ -1213,7 +1216,7 @@ set_sndbuf:
                if ((val >= 0 && val <= 6) ||
                    sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) ||
                    sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
-                       sk->sk_priority = val;
+                       WRITE_ONCE(sk->sk_priority, val);
                else
                        ret = -EPERM;
                break;
@@ -1438,7 +1441,8 @@ set_sndbuf:
                        cmpxchg(&sk->sk_pacing_status,
                                SK_PACING_NONE,
                                SK_PACING_NEEDED);
-               sk->sk_max_pacing_rate = ulval;
+               /* Pairs with READ_ONCE() from sk_getsockopt() */
+               WRITE_ONCE(sk->sk_max_pacing_rate, ulval);
                sk->sk_pacing_rate = min(sk->sk_pacing_rate, ulval);
                break;
                }
@@ -1533,7 +1537,9 @@ set_sndbuf:
                }
                if ((u8)val == SOCK_TXREHASH_DEFAULT)
                        val = READ_ONCE(sock_net(sk)->core.sysctl_txrehash);
-               /* Paired with READ_ONCE() in tcp_rtx_synack() */
+               /* Paired with READ_ONCE() in tcp_rtx_synack()
+                * and sk_getsockopt().
+                */
                WRITE_ONCE(sk->sk_txrehash, (u8)val);
                break;
 
@@ -1633,11 +1639,11 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                break;
 
        case SO_SNDBUF:
-               v.val = sk->sk_sndbuf;
+               v.val = READ_ONCE(sk->sk_sndbuf);
                break;
 
        case SO_RCVBUF:
-               v.val = sk->sk_rcvbuf;
+               v.val = READ_ONCE(sk->sk_rcvbuf);
                break;
 
        case SO_REUSEADDR:
@@ -1679,7 +1685,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                break;
 
        case SO_PRIORITY:
-               v.val = sk->sk_priority;
+               v.val = READ_ONCE(sk->sk_priority);
                break;
 
        case SO_LINGER:
@@ -1717,16 +1723,18 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
 
        case SO_RCVTIMEO_OLD:
        case SO_RCVTIMEO_NEW:
-               lv = sock_get_timeout(sk->sk_rcvtimeo, &v, SO_RCVTIMEO_OLD == optname);
+               lv = sock_get_timeout(READ_ONCE(sk->sk_rcvtimeo), &v,
+                                     SO_RCVTIMEO_OLD == optname);
                break;
 
        case SO_SNDTIMEO_OLD:
        case SO_SNDTIMEO_NEW:
-               lv = sock_get_timeout(sk->sk_sndtimeo, &v, SO_SNDTIMEO_OLD == optname);
+               lv = sock_get_timeout(READ_ONCE(sk->sk_sndtimeo), &v,
+                                     SO_SNDTIMEO_OLD == optname);
                break;
 
        case SO_RCVLOWAT:
-               v.val = sk->sk_rcvlowat;
+               v.val = READ_ONCE(sk->sk_rcvlowat);
                break;
 
        case SO_SNDLOWAT:
@@ -1770,7 +1778,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                spin_unlock(&sk->sk_peer_lock);
 
                if (!peer_pid)
-                       return -ESRCH;
+                       return -ENODATA;
 
                pidfd = pidfd_prepare(peer_pid, 0, &pidfd_file);
                put_pid(peer_pid);
@@ -1843,7 +1851,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                                                         optval, optlen, len);
 
        case SO_MARK:
-               v.val = sk->sk_mark;
+               v.val = READ_ONCE(sk->sk_mark);
                break;
 
        case SO_RCVMARK:
@@ -1862,7 +1870,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                if (!sock->ops->set_peek_off)
                        return -EOPNOTSUPP;
 
-               v.val = sk->sk_peek_off;
+               v.val = READ_ONCE(sk->sk_peek_off);
                break;
        case SO_NOFCS:
                v.val = sock_flag(sk, SOCK_NOFCS);
@@ -1892,7 +1900,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
 
 #ifdef CONFIG_NET_RX_BUSY_POLL
        case SO_BUSY_POLL:
-               v.val = sk->sk_ll_usec;
+               v.val = READ_ONCE(sk->sk_ll_usec);
                break;
        case SO_PREFER_BUSY_POLL:
                v.val = READ_ONCE(sk->sk_prefer_busy_poll);
@@ -1900,12 +1908,14 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
 #endif
 
        case SO_MAX_PACING_RATE:
+               /* The READ_ONCE() pair with the WRITE_ONCE() in sk_setsockopt() */
                if (sizeof(v.ulval) != sizeof(v.val) && len >= sizeof(v.ulval)) {
                        lv = sizeof(v.ulval);
-                       v.ulval = sk->sk_max_pacing_rate;
+                       v.ulval = READ_ONCE(sk->sk_max_pacing_rate);
                } else {
                        /* 32bit version */
-                       v.val = min_t(unsigned long, sk->sk_max_pacing_rate, ~0U);
+                       v.val = min_t(unsigned long, ~0U,
+                                     READ_ONCE(sk->sk_max_pacing_rate));
                }
                break;
 
@@ -1973,11 +1983,12 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                break;
 
        case SO_RESERVE_MEM:
-               v.val = sk->sk_reserved_mem;
+               v.val = READ_ONCE(sk->sk_reserved_mem);
                break;
 
        case SO_TXREHASH:
-               v.val = sk->sk_txrehash;
+               /* Paired with WRITE_ONCE() in sk_setsockopt() */
+               v.val = READ_ONCE(sk->sk_txrehash);
                break;
 
        default:
@@ -3148,7 +3159,7 @@ void __sk_mem_reduce_allocated(struct sock *sk, int amount)
        if (mem_cgroup_sockets_enabled && sk->sk_memcg)
                mem_cgroup_uncharge_skmem(sk->sk_memcg, amount);
 
-       if (sk_under_memory_pressure(sk) &&
+       if (sk_under_global_memory_pressure(sk) &&
            (sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)))
                sk_leave_memory_pressure(sk);
 }
@@ -3168,7 +3179,7 @@ EXPORT_SYMBOL(__sk_mem_reclaim);
 
 int sk_set_peek_off(struct sock *sk, int val)
 {
-       sk->sk_peek_off = val;
+       WRITE_ONCE(sk->sk_peek_off, val);
        return 0;
 }
 EXPORT_SYMBOL_GPL(sk_set_peek_off);
index 19538d6287144afb7dc840e31932b49339651eae..8f07fea39d9ea471adc141a8ab2de395de59cd72 100644 (file)
@@ -115,7 +115,6 @@ static void sock_map_sk_acquire(struct sock *sk)
        __acquires(&sk->sk_lock.slock)
 {
        lock_sock(sk);
-       preempt_disable();
        rcu_read_lock();
 }
 
@@ -123,7 +122,6 @@ static void sock_map_sk_release(struct sock *sk)
        __releases(&sk->sk_lock.slock)
 {
        rcu_read_unlock();
-       preempt_enable();
        release_sock(sk);
 }
 
@@ -148,13 +146,13 @@ static void sock_map_del_link(struct sock *sk,
        list_for_each_entry_safe(link, tmp, &psock->link, list) {
                if (link->link_raw == link_raw) {
                        struct bpf_map *map = link->map;
-                       struct bpf_stab *stab = container_of(map, struct bpf_stab,
-                                                            map);
-                       if (psock->saved_data_ready && stab->progs.stream_parser)
+                       struct sk_psock_progs *progs = sock_map_progs(map);
+
+                       if (psock->saved_data_ready && progs->stream_parser)
                                strp_stop = true;
-                       if (psock->saved_data_ready && stab->progs.stream_verdict)
+                       if (psock->saved_data_ready && progs->stream_verdict)
                                verdict_stop = true;
-                       if (psock->saved_data_ready && stab->progs.skb_verdict)
+                       if (psock->saved_data_ready && progs->skb_verdict)
                                verdict_stop = true;
                        list_del(&link->list);
                        sk_psock_free_link(link);
index c0c4381285759ff639e01f4fda3fe1df2b01ef5f..2e6b8c8fd2dedd08c7f3e10c81ee1697d13b5f82 100644 (file)
@@ -980,7 +980,7 @@ static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
                return -EOPNOTSUPP;
 
        ret = nla_parse_nested_deprecated(data, DCB_BCN_ATTR_MAX,
-                                         tb[DCB_ATTR_BCN], dcbnl_pfc_up_nest,
+                                         tb[DCB_ATTR_BCN], dcbnl_bcn_nest,
                                          NULL);
        if (ret)
                return ret;
index 7249ef218178743ce7936fcf2f605616a419370e..d29d1163203d965361ed9b632321cdfd36f0eb76 100644 (file)
@@ -238,8 +238,8 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req
                opt = ireq->ipv6_opt;
                if (!opt)
                        opt = rcu_dereference(np->opt);
-               err = ip6_xmit(sk, skb, &fl6, sk->sk_mark, opt, np->tclass,
-                              sk->sk_priority);
+               err = ip6_xmit(sk, skb, &fl6, READ_ONCE(sk->sk_mark), opt,
+                              np->tclass, sk->sk_priority);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
index b8a24734385ef75c3de33862a6bcd248fdd3d723..fd2eb148d24de4d1b9e40c6721577ed7f11b5a6c 100644 (file)
@@ -187,7 +187,7 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
 
        /* And store cached results */
        icsk->icsk_pmtu_cookie = pmtu;
-       dp->dccps_mss_cache = cur_mps;
+       WRITE_ONCE(dp->dccps_mss_cache, cur_mps);
 
        return cur_mps;
 }
index f331e5977a8447d9884fe1ddbcac72ed32f5dece..4e3266e4d7c3c4595ac7f0f8e5e48c0cc98724de 100644 (file)
@@ -630,7 +630,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
                return dccp_getsockopt_service(sk, len,
                                               (__be32 __user *)optval, optlen);
        case DCCP_SOCKOPT_GET_CUR_MPS:
-               val = dp->dccps_mss_cache;
+               val = READ_ONCE(dp->dccps_mss_cache);
                break;
        case DCCP_SOCKOPT_AVAILABLE_CCIDS:
                return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);
@@ -739,7 +739,7 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        trace_dccp_probe(sk, len);
 
-       if (len > dp->dccps_mss_cache)
+       if (len > READ_ONCE(dp->dccps_mss_cache))
                return -EMSGSIZE;
 
        lock_sock(sk);
@@ -772,6 +772,12 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                goto out_discard;
        }
 
+       /* We need to check dccps_mss_cache after socket is locked. */
+       if (len > dp->dccps_mss_cache) {
+               rc = -EMSGSIZE;
+               goto out_discard;
+       }
+
        skb_reserve(skb, sk->sk_prot->max_header);
        rc = memcpy_from_msg(skb_put(skb, len), msg, len);
        if (rc != 0)
index 0ce8fd311c78758502ca1ced0961aebc024eb13f..2f6195d7b7412741533773ac4af2358da2fbf32c 100644 (file)
@@ -1727,8 +1727,15 @@ int dsa_port_phylink_create(struct dsa_port *dp)
            ds->ops->phylink_mac_an_restart)
                dp->pl_config.legacy_pre_march2020 = true;
 
-       if (ds->ops->phylink_get_caps)
+       if (ds->ops->phylink_get_caps) {
                ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config);
+       } else {
+               /* For legacy drivers */
+               __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+                         dp->pl_config.supported_interfaces);
+               __set_bit(PHY_INTERFACE_MODE_GMII,
+                         dp->pl_config.supported_interfaces);
+       }
 
        pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn),
                            mode, &dsa_port_phylink_mac_ops);
index b812eb36f0e367b976876c6a9be90babbb6de1f4..f7426926a10413b42ec3b99d97f59445b6d1becc 100644 (file)
@@ -150,7 +150,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
        }
 #endif
 
-       if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, sk->sk_mark))
+       if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, READ_ONCE(sk->sk_mark)))
                goto errout;
 
        if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) ||
@@ -799,7 +799,7 @@ int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
        entry.ifindex = sk->sk_bound_dev_if;
        entry.userlocks = sk_fullsock(sk) ? sk->sk_userlocks : 0;
        if (sk_fullsock(sk))
-               entry.mark = sk->sk_mark;
+               entry.mark = READ_ONCE(sk->sk_mark);
        else if (sk->sk_state == TCP_NEW_SYN_RECV)
                entry.mark = inet_rsk(inet_reqsk(sk))->ir_mark;
        else if (sk->sk_state == TCP_TIME_WAIT)
index 6e70839257f74fa3f4019305280022a33ee00240..6ba1a0fafbaab09631a0700d6b8403c698b6446f 100644 (file)
@@ -184,9 +184,9 @@ int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,
                ip_options_build(skb, &opt->opt, daddr, rt);
        }
 
-       skb->priority = sk->sk_priority;
+       skb->priority = READ_ONCE(sk->sk_priority);
        if (!skb->mark)
-               skb->mark = sk->sk_mark;
+               skb->mark = READ_ONCE(sk->sk_mark);
 
        /* Send it out. */
        return ip_local_out(net, skb->sk, skb);
@@ -528,8 +528,8 @@ packet_routed:
                             skb_shinfo(skb)->gso_segs ?: 1);
 
        /* TODO : should we use skb->sk here instead of sk ? */
-       skb->priority = sk->sk_priority;
-       skb->mark = sk->sk_mark;
+       skb->priority = READ_ONCE(sk->sk_priority);
+       skb->mark = READ_ONCE(sk->sk_mark);
 
        res = ip_local_out(net, sk, skb);
        rcu_read_unlock();
@@ -1158,10 +1158,15 @@ alloc_new_skb:
                        }
 
                        copy = datalen - transhdrlen - fraggap - pagedlen;
+                       /* [!] NOTE: copy will be negative if pagedlen>0
+                        * because then the equation reduces to -fraggap.
+                        */
                        if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
                                err = -EFAULT;
                                kfree_skb(skb);
                                goto error;
+                       } else if (flags & MSG_SPLICE_PAGES) {
+                               copy = 0;
                        }
 
                        offset += copy;
@@ -1209,6 +1214,10 @@ alloc_new_skb:
                } else if (flags & MSG_SPLICE_PAGES) {
                        struct msghdr *msg = from;
 
+                       err = -EIO;
+                       if (WARN_ON_ONCE(copy > msg->msg_iter.count))
+                               goto error;
+
                        err = skb_splice_from_iter(skb, &msg->msg_iter, copy,
                                                   sk->sk_allocation);
                        if (err < 0)
index 8e97d8d4cc9d910a0cc29897be4820b53b019433..d41bce8927b2cca825a804dc113450b62262cc94 100644 (file)
@@ -592,7 +592,7 @@ void __ip_sock_set_tos(struct sock *sk, int val)
        }
        if (inet_sk(sk)->tos != val) {
                inet_sk(sk)->tos = val;
-               sk->sk_priority = rt_tos2priority(val);
+               WRITE_ONCE(sk->sk_priority, rt_tos2priority(val));
                sk_dst_reset(sk);
        }
 }
index 92c02c886fe735ba0dd784181fe297acf8a98faa..586b1b3e35b805d46158531ae8e7b49122abbaa7 100644 (file)
@@ -224,7 +224,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
                .un.frag.__unused       = 0,
                .un.frag.mtu            = htons(mtu),
        };
-       icmph->checksum = ip_compute_csum(icmph, len);
+       icmph->checksum = csum_fold(skb_checksum(skb, 0, len, 0));
        skb_reset_transport_header(skb);
 
        niph = skb_push(skb, sizeof(*niph));
index 53bfd8af69203619cd775171c2e8b43cca3449b1..d1e7d0ceb7edd464859c9768912d9b132bd36365 100644 (file)
@@ -287,12 +287,12 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 
        switch (skb->protocol) {
        case htons(ETH_P_IP):
-               xfrm_decode_session(skb, &fl, AF_INET);
                memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+               xfrm_decode_session(skb, &fl, AF_INET);
                break;
        case htons(ETH_P_IPV6):
-               xfrm_decode_session(skb, &fl, AF_INET6);
                memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+               xfrm_decode_session(skb, &fl, AF_INET6);
                break;
        default:
                goto tx_err;
index f95142e56da057179bbccc48c65928abf28aef28..be5498f5dd3192feddf4fbb919bfc9a26f29cb26 100644 (file)
@@ -3221,13 +3221,9 @@ static int rtm_dump_nexthop(struct sk_buff *skb, struct netlink_callback *cb)
                                     &rtm_dump_nexthop_cb, &filter);
        if (err < 0) {
                if (likely(skb->len))
-                       goto out;
-               goto out_err;
+                       err = skb->len;
        }
 
-out:
-       err = skb->len;
-out_err:
        cb->seq = net->nexthop.seq;
        nl_dump_check_consistent(cb, nlmsg_hdr(skb));
        return err;
@@ -3367,25 +3363,19 @@ static int rtm_dump_nexthop_bucket_nh(struct sk_buff *skb,
                    dd->filter.res_bucket_nh_id != nhge->nh->id)
                        continue;
 
+               dd->ctx->bucket_index = bucket_index;
                err = nh_fill_res_bucket(skb, nh, bucket, bucket_index,
                                         RTM_NEWNEXTHOPBUCKET, portid,
                                         cb->nlh->nlmsg_seq, NLM_F_MULTI,
                                         cb->extack);
-               if (err < 0) {
-                       if (likely(skb->len))
-                               goto out;
-                       goto out_err;
-               }
+               if (err)
+                       return err;
        }
 
        dd->ctx->done_nh_idx = dd->ctx->nh.idx + 1;
-       bucket_index = 0;
+       dd->ctx->bucket_index = 0;
 
-out:
-       err = skb->len;
-out_err:
-       dd->ctx->bucket_index = bucket_index;
-       return err;
+       return 0;
 }
 
 static int rtm_dump_nexthop_bucket_cb(struct sk_buff *skb,
@@ -3434,13 +3424,9 @@ static int rtm_dump_nexthop_bucket(struct sk_buff *skb,
 
        if (err < 0) {
                if (likely(skb->len))
-                       goto out;
-               goto out_err;
+                       err = skb->len;
        }
 
-out:
-       err = skb->len;
-out_err:
        cb->seq = net->nexthop.seq;
        nl_dump_check_consistent(cb, nlmsg_hdr(skb));
        return err;
index 7782ff5e65399b4d0c8ac5d25b8d999b0a1a2e71..cb381f5aa46438394cdec520a99f7a8bc67fcfb9 100644 (file)
@@ -348,7 +348,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
                goto error;
        skb_reserve(skb, hlen);
 
-       skb->priority = sk->sk_priority;
+       skb->priority = READ_ONCE(sk->sk_priority);
        skb->mark = sockc->mark;
        skb->tstamp = sockc->transmit_time;
        skb_dst_set(skb, &rt->dst);
index 98d7e6ba7493be243038433d204f7a4127d2f4f2..92fede388d52052ee3bd2337298b8cb0608dc362 100644 (file)
@@ -518,7 +518,7 @@ static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
                const struct inet_sock *inet = inet_sk(sk);
 
                oif = sk->sk_bound_dev_if;
-               mark = sk->sk_mark;
+               mark = READ_ONCE(sk->sk_mark);
                tos = ip_sock_rt_tos(sk);
                scope = ip_sock_rt_scope(sk);
                prot = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol;
@@ -552,7 +552,7 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
        inet_opt = rcu_dereference(inet->inet_opt);
        if (inet_opt && inet_opt->opt.srr)
                daddr = inet_opt->opt.faddr;
-       flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark,
+       flowi4_init_output(fl4, sk->sk_bound_dev_if, READ_ONCE(sk->sk_mark),
                           ip_sock_rt_tos(sk) & IPTOS_RT_MASK,
                           ip_sock_rt_scope(sk),
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
index 0696420146369a8786f0dbab142e45aa09fbac00..a59cc4b8386113577d966a3efce53a13f51e8b06 100644 (file)
@@ -931,9 +931,9 @@ static void tcp_v4_send_ack(const struct sock *sk,
        ctl_sk = this_cpu_read(ipv4_tcp_sk);
        sock_net_set(ctl_sk, net);
        ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
-                          inet_twsk(sk)->tw_mark : sk->sk_mark;
+                          inet_twsk(sk)->tw_mark : READ_ONCE(sk->sk_mark);
        ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ?
-                          inet_twsk(sk)->tw_priority : sk->sk_priority;
+                          inet_twsk(sk)->tw_priority : READ_ONCE(sk->sk_priority);
        transmit_time = tcp_transmit_time(sk);
        ip_send_unicast_reply(ctl_sk,
                              skb, &TCP_SKB_CB(skb)->header.h4.opt,
index 82f4575f9cd90049a5ad4c7329ad1ddc28fc1aa0..99ac5efe244d3c654deaa8f8c0fffeeb5d5597b1 100644 (file)
@@ -40,7 +40,7 @@ struct tcp_fastopen_metrics {
 
 struct tcp_metrics_block {
        struct tcp_metrics_block __rcu  *tcpm_next;
-       possible_net_t                  tcpm_net;
+       struct net                      *tcpm_net;
        struct inetpeer_addr            tcpm_saddr;
        struct inetpeer_addr            tcpm_daddr;
        unsigned long                   tcpm_stamp;
@@ -51,34 +51,38 @@ struct tcp_metrics_block {
        struct rcu_head                 rcu_head;
 };
 
-static inline struct net *tm_net(struct tcp_metrics_block *tm)
+static inline struct net *tm_net(const struct tcp_metrics_block *tm)
 {
-       return read_pnet(&tm->tcpm_net);
+       /* Paired with the WRITE_ONCE() in tcpm_new() */
+       return READ_ONCE(tm->tcpm_net);
 }
 
 static bool tcp_metric_locked(struct tcp_metrics_block *tm,
                              enum tcp_metric_index idx)
 {
-       return tm->tcpm_lock & (1 << idx);
+       /* Paired with WRITE_ONCE() in tcpm_suck_dst() */
+       return READ_ONCE(tm->tcpm_lock) & (1 << idx);
 }
 
-static u32 tcp_metric_get(struct tcp_metrics_block *tm,
+static u32 tcp_metric_get(const struct tcp_metrics_block *tm,
                          enum tcp_metric_index idx)
 {
-       return tm->tcpm_vals[idx];
+       /* Paired with WRITE_ONCE() in tcp_metric_set() */
+       return READ_ONCE(tm->tcpm_vals[idx]);
 }
 
 static void tcp_metric_set(struct tcp_metrics_block *tm,
                           enum tcp_metric_index idx,
                           u32 val)
 {
-       tm->tcpm_vals[idx] = val;
+       /* Paired with READ_ONCE() in tcp_metric_get() */
+       WRITE_ONCE(tm->tcpm_vals[idx], val);
 }
 
 static bool addr_same(const struct inetpeer_addr *a,
                      const struct inetpeer_addr *b)
 {
-       return inetpeer_addr_cmp(a, b) == 0;
+       return (a->family == b->family) && !inetpeer_addr_cmp(a, b);
 }
 
 struct tcpm_hash_bucket {
@@ -89,6 +93,7 @@ static struct tcpm_hash_bucket        *tcp_metrics_hash __read_mostly;
 static unsigned int            tcp_metrics_hash_log __read_mostly;
 
 static DEFINE_SPINLOCK(tcp_metrics_lock);
+static DEFINE_SEQLOCK(fastopen_seqlock);
 
 static void tcpm_suck_dst(struct tcp_metrics_block *tm,
                          const struct dst_entry *dst,
@@ -97,7 +102,7 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm,
        u32 msval;
        u32 val;
 
-       tm->tcpm_stamp = jiffies;
+       WRITE_ONCE(tm->tcpm_stamp, jiffies);
 
        val = 0;
        if (dst_metric_locked(dst, RTAX_RTT))
@@ -110,30 +115,42 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm,
                val |= 1 << TCP_METRIC_CWND;
        if (dst_metric_locked(dst, RTAX_REORDERING))
                val |= 1 << TCP_METRIC_REORDERING;
-       tm->tcpm_lock = val;
+       /* Paired with READ_ONCE() in tcp_metric_locked() */
+       WRITE_ONCE(tm->tcpm_lock, val);
 
        msval = dst_metric_raw(dst, RTAX_RTT);
-       tm->tcpm_vals[TCP_METRIC_RTT] = msval * USEC_PER_MSEC;
+       tcp_metric_set(tm, TCP_METRIC_RTT, msval * USEC_PER_MSEC);
 
        msval = dst_metric_raw(dst, RTAX_RTTVAR);
-       tm->tcpm_vals[TCP_METRIC_RTTVAR] = msval * USEC_PER_MSEC;
-       tm->tcpm_vals[TCP_METRIC_SSTHRESH] = dst_metric_raw(dst, RTAX_SSTHRESH);
-       tm->tcpm_vals[TCP_METRIC_CWND] = dst_metric_raw(dst, RTAX_CWND);
-       tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING);
+       tcp_metric_set(tm, TCP_METRIC_RTTVAR, msval * USEC_PER_MSEC);
+       tcp_metric_set(tm, TCP_METRIC_SSTHRESH,
+                      dst_metric_raw(dst, RTAX_SSTHRESH));
+       tcp_metric_set(tm, TCP_METRIC_CWND,
+                      dst_metric_raw(dst, RTAX_CWND));
+       tcp_metric_set(tm, TCP_METRIC_REORDERING,
+                      dst_metric_raw(dst, RTAX_REORDERING));
        if (fastopen_clear) {
+               write_seqlock(&fastopen_seqlock);
                tm->tcpm_fastopen.mss = 0;
                tm->tcpm_fastopen.syn_loss = 0;
                tm->tcpm_fastopen.try_exp = 0;
                tm->tcpm_fastopen.cookie.exp = false;
                tm->tcpm_fastopen.cookie.len = 0;
+               write_sequnlock(&fastopen_seqlock);
        }
 }
 
 #define TCP_METRICS_TIMEOUT            (60 * 60 * HZ)
 
-static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
+static void tcpm_check_stamp(struct tcp_metrics_block *tm,
+                            const struct dst_entry *dst)
 {
-       if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
+       unsigned long limit;
+
+       if (!tm)
+               return;
+       limit = READ_ONCE(tm->tcpm_stamp) + TCP_METRICS_TIMEOUT;
+       if (unlikely(time_after(jiffies, limit)))
                tcpm_suck_dst(tm, dst, false);
 }
 
@@ -174,20 +191,23 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
                oldest = deref_locked(tcp_metrics_hash[hash].chain);
                for (tm = deref_locked(oldest->tcpm_next); tm;
                     tm = deref_locked(tm->tcpm_next)) {
-                       if (time_before(tm->tcpm_stamp, oldest->tcpm_stamp))
+                       if (time_before(READ_ONCE(tm->tcpm_stamp),
+                                       READ_ONCE(oldest->tcpm_stamp)))
                                oldest = tm;
                }
                tm = oldest;
        } else {
-               tm = kmalloc(sizeof(*tm), GFP_ATOMIC);
+               tm = kzalloc(sizeof(*tm), GFP_ATOMIC);
                if (!tm)
                        goto out_unlock;
        }
-       write_pnet(&tm->tcpm_net, net);
+       /* Paired with the READ_ONCE() in tm_net() */
+       WRITE_ONCE(tm->tcpm_net, net);
+
        tm->tcpm_saddr = *saddr;
        tm->tcpm_daddr = *daddr;
 
-       tcpm_suck_dst(tm, dst, true);
+       tcpm_suck_dst(tm, dst, reclaim);
 
        if (likely(!reclaim)) {
                tm->tcpm_next = tcp_metrics_hash[hash].chain;
@@ -434,7 +454,7 @@ void tcp_update_metrics(struct sock *sk)
                                               tp->reordering);
                }
        }
-       tm->tcpm_stamp = jiffies;
+       WRITE_ONCE(tm->tcpm_stamp, jiffies);
 out_unlock:
        rcu_read_unlock();
 }
@@ -539,8 +559,6 @@ bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst)
        return ret;
 }
 
-static DEFINE_SEQLOCK(fastopen_seqlock);
-
 void tcp_fastopen_cache_get(struct sock *sk, u16 *mss,
                            struct tcp_fastopen_cookie *cookie)
 {
@@ -647,7 +665,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg,
        }
 
        if (nla_put_msecs(msg, TCP_METRICS_ATTR_AGE,
-                         jiffies - tm->tcpm_stamp,
+                         jiffies - READ_ONCE(tm->tcpm_stamp),
                          TCP_METRICS_ATTR_PAD) < 0)
                goto nla_put_failure;
 
@@ -658,7 +676,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg,
                if (!nest)
                        goto nla_put_failure;
                for (i = 0; i < TCP_METRIC_MAX_KERNEL + 1; i++) {
-                       u32 val = tm->tcpm_vals[i];
+                       u32 val = tcp_metric_get(tm, i);
 
                        if (!val)
                                continue;
index 470f581eedd438b3bbd6ae4973c7a6f01ee1724f..206418b6d7c48b545fa6740b472fe6d083dd9830 100644 (file)
@@ -591,7 +591,9 @@ out_reset_timer:
            tcp_stream_is_thin(tp) &&
            icsk->icsk_retransmits <= TCP_THIN_LINEAR_RETRIES) {
                icsk->icsk_backoff = 0;
-               icsk->icsk_rto = min(__tcp_set_rto(tp), TCP_RTO_MAX);
+               icsk->icsk_rto = clamp(__tcp_set_rto(tp),
+                                      tcp_rto_min(sk),
+                                      TCP_RTO_MAX);
        } else if (sk->sk_state != TCP_SYN_SENT ||
                   icsk->icsk_backoff >
                   READ_ONCE(net->ipv4.sysctl_tcp_syn_linear_timeouts)) {
index 42a96b3547c9fadc7d508aff9c57b553cf5fad4d..abfa860367aa9532ee7be237ac87cca05772cc8e 100644 (file)
 #include <net/sock_reuseport.h>
 #include <net/addrconf.h>
 #include <net/udp_tunnel.h>
+#include <net/gro.h>
 #if IS_ENABLED(CONFIG_IPV6)
 #include <net/ipv6_stubs.h>
 #endif
@@ -555,10 +556,13 @@ struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
 {
        const struct iphdr *iph = ip_hdr(skb);
        struct net *net = dev_net(skb->dev);
+       int iif, sdif;
+
+       inet_get_iif_sdif(skb, &iif, &sdif);
 
        return __udp4_lib_lookup(net, iph->saddr, sport,
-                                iph->daddr, dport, inet_iif(skb),
-                                inet_sdif(skb), net->ipv4.udp_table, NULL);
+                                iph->daddr, dport, iif,
+                                sdif, net->ipv4.udp_table, NULL);
 }
 
 /* Must be called under rcu_read_lock().
index f402946da344bf0f9c4ef303419fc8c7997cdda2..0f46b3c2e4ac5427a5d39586086048afe22f34f1 100644 (file)
@@ -609,10 +609,13 @@ static struct sock *udp4_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
 {
        const struct iphdr *iph = skb_gro_network_header(skb);
        struct net *net = dev_net(skb->dev);
+       int iif, sdif;
+
+       inet_get_iif_sdif(skb, &iif, &sdif);
 
        return __udp4_lib_lookup(net, iph->saddr, sport,
-                                iph->daddr, dport, inet_iif(skb),
-                                inet_sdif(skb), net->ipv4.udp_table, NULL);
+                                iph->daddr, dport, iif,
+                                sdif, net->ipv4.udp_table, NULL);
 }
 
 INDIRECT_CALLABLE_SCOPE
index 658bfed1df8b178506b0be9ce05b330fc2affdaa..08d4b7132d4c45b56486140c4daaf51866b56f2d 100644 (file)
@@ -152,7 +152,7 @@ config INET6_TUNNEL
        default n
 
 config IPV6_VTI
-tristate "Virtual (secure) IPv6: tunneling"
+       tristate "Virtual (secure) IPv6: tunneling"
        select IPV6_TUNNEL
        select NET_IP_TUNNEL
        select XFRM
index 10b222865d46a8b7d51028f89ca10208031b8700..73c85d4e0e9cd5e97943e4d6fb8bd99458e1ee46 100644 (file)
@@ -568,12 +568,12 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
                    vti6_addr_conflict(t, ipv6_hdr(skb)))
                        goto tx_err;
 
-               xfrm_decode_session(skb, &fl, AF_INET6);
                memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+               xfrm_decode_session(skb, &fl, AF_INET6);
                break;
        case htons(ETH_P_IP):
-               xfrm_decode_session(skb, &fl, AF_INET);
                memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+               xfrm_decode_session(skb, &fl, AF_INET);
                break;
        default:
                goto tx_err;
index cc3d5ad17257371812469ac344d7fc4549613e7a..67a3b8f6e72b115e8fae07d7c7d358a7ac1659a5 100644 (file)
@@ -1073,7 +1073,7 @@ static int ip6mr_cache_report(const struct mr_table *mrt, struct sk_buff *pkt,
                   And all this only to mangle msg->im6_msgtype and
                   to set msg->im6_mbz to "mbz" :-)
                 */
-               skb_push(skb, -skb_network_offset(pkt));
+               __skb_pull(skb, skb_network_offset(pkt));
 
                skb_push(skb, sizeof(*msg));
                skb_reset_transport_header(skb);
index 18634ebd20a47d2d0d707c164e0691d3beb60427..a42be96ae209bb05ae4a17a9352fdc8960d824d9 100644 (file)
@@ -197,7 +197,8 @@ static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
 static inline int ndisc_is_useropt(const struct net_device *dev,
                                   struct nd_opt_hdr *opt)
 {
-       return opt->nd_opt_type == ND_OPT_RDNSS ||
+       return opt->nd_opt_type == ND_OPT_PREFIX_INFO ||
+               opt->nd_opt_type == ND_OPT_RDNSS ||
                opt->nd_opt_type == ND_OPT_DNSSL ||
                opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL ||
                opt->nd_opt_type == ND_OPT_PREF64 ||
index f804c11e2146cba9e9b8c10337341dc3fb4e0143..c2c291827a2ce990a62466ece52ecb7dc9d30490 100644 (file)
@@ -120,7 +120,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        ipcm6_init_sk(&ipc6, np);
        ipc6.sockc.tsflags = sk->sk_tsflags;
-       ipc6.sockc.mark = sk->sk_mark;
+       ipc6.sockc.mark = READ_ONCE(sk->sk_mark);
 
        fl6.flowi6_oif = oif;
 
index ac1cef094c5f200d34a45eeb06f2f7356c87ad6d..49381f35b623c4fd717e44f7a6058965bb54a56f 100644 (file)
@@ -614,7 +614,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
        skb_reserve(skb, hlen);
 
        skb->protocol = htons(ETH_P_IPV6);
-       skb->priority = sk->sk_priority;
+       skb->priority = READ_ONCE(sk->sk_priority);
        skb->mark = sockc->mark;
        skb->tstamp = sockc->transmit_time;
 
@@ -774,12 +774,12 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
         */
        memset(&fl6, 0, sizeof(fl6));
 
-       fl6.flowi6_mark = sk->sk_mark;
+       fl6.flowi6_mark = READ_ONCE(sk->sk_mark);
        fl6.flowi6_uid = sk->sk_uid;
 
        ipcm6_init(&ipc6);
        ipc6.sockc.tsflags = sk->sk_tsflags;
-       ipc6.sockc.mark = sk->sk_mark;
+       ipc6.sockc.mark = fl6.flowi6_mark;
 
        if (sin6) {
                if (addr_len < SIN6_LEN_RFC2133)
index 64e873f5895f1907b813d675a9ea46f5db3f429c..56a55585eb798b7885bcc32cc853becd1f120c94 100644 (file)
@@ -2951,7 +2951,8 @@ void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
        if (!oif && skb->dev)
                oif = l3mdev_master_ifindex(skb->dev);
 
-       ip6_update_pmtu(skb, sock_net(sk), mtu, oif, sk->sk_mark, sk->sk_uid);
+       ip6_update_pmtu(skb, sock_net(sk), mtu, oif, READ_ONCE(sk->sk_mark),
+                       sk->sk_uid);
 
        dst = __sk_dst_get(sk);
        if (!dst || !dst->obsolete ||
@@ -3172,8 +3173,8 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif)
 
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 {
-       ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark,
-                    sk->sk_uid);
+       ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if,
+                    READ_ONCE(sk->sk_mark), sk->sk_uid);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_redirect);
 
index 4714eb695913d43f03f533483560ab8cb5bf555d..6e86721e1cdbb8d47b754a2675f6ab1643c7342c 100644 (file)
@@ -564,8 +564,8 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
                opt = ireq->ipv6_opt;
                if (!opt)
                        opt = rcu_dereference(np->opt);
-               err = ip6_xmit(sk, skb, fl6, skb->mark ? : sk->sk_mark, opt,
-                              tclass, sk->sk_priority);
+               err = ip6_xmit(sk, skb, fl6, skb->mark ? : READ_ONCE(sk->sk_mark),
+                              opt, tclass, sk->sk_priority);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
@@ -939,7 +939,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
                if (sk->sk_state == TCP_TIME_WAIT)
                        mark = inet_twsk(sk)->tw_mark;
                else
-                       mark = sk->sk_mark;
+                       mark = READ_ONCE(sk->sk_mark);
                skb_set_delivery_time(buff, tcp_transmit_time(sk), true);
        }
        if (txhash) {
@@ -1128,7 +1128,8 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
                        tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
                        READ_ONCE(req->ts_recent), sk->sk_bound_dev_if,
                        tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, l3index),
-                       ipv6_get_dsfield(ipv6_hdr(skb)), 0, sk->sk_priority,
+                       ipv6_get_dsfield(ipv6_hdr(skb)), 0,
+                       READ_ONCE(sk->sk_priority),
                        READ_ONCE(tcp_rsk(req)->txhash));
 }
 
index b7c972aa09a75404e0edb33f0354c53702c991f8..f787e6b8424c7b339354f18f85a7d940fe8649f4 100644 (file)
@@ -51,6 +51,7 @@
 #include <net/inet6_hashtables.h>
 #include <net/busy_poll.h>
 #include <net/sock_reuseport.h>
+#include <net/gro.h>
 
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -300,10 +301,13 @@ struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
 {
        const struct ipv6hdr *iph = ipv6_hdr(skb);
        struct net *net = dev_net(skb->dev);
+       int iif, sdif;
+
+       inet6_get_iif_sdif(skb, &iif, &sdif);
 
        return __udp6_lib_lookup(net, &iph->saddr, sport,
-                                &iph->daddr, dport, inet6_iif(skb),
-                                inet6_sdif(skb), net->ipv4.udp_table, NULL);
+                                &iph->daddr, dport, iif,
+                                sdif, net->ipv4.udp_table, NULL);
 }
 
 /* Must be called under rcu_read_lock().
@@ -624,7 +628,7 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        if (type == NDISC_REDIRECT) {
                if (tunnel) {
                        ip6_redirect(skb, sock_net(sk), inet6_iif(skb),
-                                    sk->sk_mark, sk->sk_uid);
+                                    READ_ONCE(sk->sk_mark), sk->sk_uid);
                } else {
                        ip6_sk_redirect(skb, sk);
                }
@@ -1356,7 +1360,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        ipcm6_init(&ipc6);
        ipc6.gso_size = READ_ONCE(up->gso_size);
        ipc6.sockc.tsflags = sk->sk_tsflags;
-       ipc6.sockc.mark = sk->sk_mark;
+       ipc6.sockc.mark = READ_ONCE(sk->sk_mark);
 
        /* destination address check */
        if (sin6) {
index 09fa7a42cb937a5bc5b2e35f92ca9bae6690b3bf..6b95ba241ebe2af7e5f2760d8a9c1d78f08579c5 100644 (file)
@@ -118,10 +118,13 @@ static struct sock *udp6_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
 {
        const struct ipv6hdr *iph = skb_gro_network_header(skb);
        struct net *net = dev_net(skb->dev);
+       int iif, sdif;
+
+       inet6_get_iif_sdif(skb, &iif, &sdif);
 
        return __udp6_lib_lookup(net, &iph->saddr, sport,
-                                &iph->daddr, dport, inet6_iif(skb),
-                                inet6_sdif(skb), net->ipv4.udp_table, NULL);
+                                &iph->daddr, dport, iif,
+                                sdif, net->ipv4.udp_table, NULL);
 }
 
 INDIRECT_CALLABLE_SCOPE
index ede3c6a603532551ee70cb870199737b0942ca25..b4ea4cf9fad4305cda4bc068d7b43dc43a52028d 100644 (file)
@@ -1848,9 +1848,9 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
        if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
                struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
 
-               if ((xfilter->sadb_x_filter_splen >=
+               if ((xfilter->sadb_x_filter_splen >
                        (sizeof(xfrm_address_t) << 3)) ||
-                   (xfilter->sadb_x_filter_dplen >=
+                   (xfilter->sadb_x_filter_dplen >
                        (sizeof(xfrm_address_t) << 3))) {
                        mutex_unlock(&pfk->dump_lock);
                        return -EINVAL;
index b1623f9c4f921791ab541ecf93695ea19addaa5a..ff78217f0cb1289bdf1022f0414e1188d5e786d1 100644 (file)
@@ -519,7 +519,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        /* Get and verify the address */
        memset(&fl6, 0, sizeof(fl6));
 
-       fl6.flowi6_mark = sk->sk_mark;
+       fl6.flowi6_mark = READ_ONCE(sk->sk_mark);
        fl6.flowi6_uid = sk->sk_uid;
 
        ipcm6_init(&ipc6);
index 3317d1cca15688f33b7deeb256a8ee4867337cca..d80658547836f75bd0cbbcff62959ee1291b7bfd 100644 (file)
@@ -2335,7 +2335,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
 
        lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
 
-       if (flags & MPTCP_CF_FASTCLOSE) {
+       if ((flags & MPTCP_CF_FASTCLOSE) && !__mptcp_check_fallback(msk)) {
                /* be sure to force the tcp_disconnect() path,
                 * to generate the egress reset
                 */
@@ -3328,7 +3328,7 @@ static void mptcp_release_cb(struct sock *sk)
 
        if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags))
                __mptcp_clean_una_wakeup(sk);
-       if (unlikely(&msk->cb_flags)) {
+       if (unlikely(msk->cb_flags)) {
                /* be sure to set the current sk state before tacking actions
                 * depending on sk_state, that is processing MPTCP_ERROR_REPORT
                 */
index 37fbe22e2433d551d45e1ad148e8603bad5b5733..ba2a873a4d2e657186513de7edc47f501b989309 100644 (file)
@@ -325,7 +325,6 @@ struct mptcp_sock {
        u32             subflow_id;
        u32             setsockopt_seq;
        char            ca_name[TCP_CA_NAME_MAX];
-       struct mptcp_sock       *dl_next;
 };
 
 #define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock)
index 63f7a09335c5c9489ce211790502eae9b6894aac..a3f1fe810cc961bf689fe8edda49d227a3170f91 100644 (file)
@@ -103,7 +103,7 @@ static void mptcp_sol_socket_sync_intval(struct mptcp_sock *msk, int optname, in
                        break;
                case SO_MARK:
                        if (READ_ONCE(ssk->sk_mark) != sk->sk_mark) {
-                               ssk->sk_mark = sk->sk_mark;
+                               WRITE_ONCE(ssk->sk_mark, sk->sk_mark);
                                sk_dst_reset(ssk);
                        }
                        break;
index 9ee3b7abbaf6dd2340c1d2142e834e898a7fcfa8..94ae7dd01c65e0ccda7955afbd107a43bb30f498 100644 (file)
@@ -1793,16 +1793,31 @@ static void subflow_state_change(struct sock *sk)
 void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk)
 {
        struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue;
-       struct mptcp_sock *msk, *next, *head = NULL;
-       struct request_sock *req;
-       struct sock *sk;
+       struct request_sock *req, *head, *tail;
+       struct mptcp_subflow_context *subflow;
+       struct sock *sk, *ssk;
 
-       /* build a list of all unaccepted mptcp sockets */
+       /* Due to lock dependencies no relevant lock can be acquired under rskq_lock.
+        * Splice the req list, so that accept() can not reach the pending ssk after
+        * the listener socket is released below.
+        */
        spin_lock_bh(&queue->rskq_lock);
-       for (req = queue->rskq_accept_head; req; req = req->dl_next) {
-               struct mptcp_subflow_context *subflow;
-               struct sock *ssk = req->sk;
+       head = queue->rskq_accept_head;
+       tail = queue->rskq_accept_tail;
+       queue->rskq_accept_head = NULL;
+       queue->rskq_accept_tail = NULL;
+       spin_unlock_bh(&queue->rskq_lock);
+
+       if (!head)
+               return;
 
+       /* can't acquire the msk socket lock under the subflow one,
+        * or will cause ABBA deadlock
+        */
+       release_sock(listener_ssk);
+
+       for (req = head; req; req = req->dl_next) {
+               ssk = req->sk;
                if (!sk_is_mptcp(ssk))
                        continue;
 
@@ -1810,32 +1825,10 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s
                if (!subflow || !subflow->conn)
                        continue;
 
-               /* skip if already in list */
                sk = subflow->conn;
-               msk = mptcp_sk(sk);
-               if (msk->dl_next || msk == head)
-                       continue;
-
                sock_hold(sk);
-               msk->dl_next = head;
-               head = msk;
-       }
-       spin_unlock_bh(&queue->rskq_lock);
-       if (!head)
-               return;
-
-       /* can't acquire the msk socket lock under the subflow one,
-        * or will cause ABBA deadlock
-        */
-       release_sock(listener_ssk);
-
-       for (msk = head; msk; msk = next) {
-               sk = (struct sock *)msk;
 
                lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
-               next = msk->dl_next;
-               msk->dl_next = NULL;
-
                __mptcp_unaccepted_force_close(sk);
                release_sock(sk);
 
@@ -1859,6 +1852,13 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s
 
        /* we are still under the listener msk socket lock */
        lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING);
+
+       /* restore the listener queue, to let the TCP code clean it up */
+       spin_lock_bh(&queue->rskq_lock);
+       WARN_ON_ONCE(queue->rskq_accept_head);
+       queue->rskq_accept_head = head;
+       queue->rskq_accept_tail = tail;
+       spin_unlock_bh(&queue->rskq_lock);
 }
 
 static int subflow_ulp_init(struct sock *sk)
index 62606fb44d02724b1e68234f300159cc69251373..4bb0d90eca1cd67a8b83f7ccc1a63038b41aaefb 100644 (file)
@@ -1876,6 +1876,7 @@ static int
 proc_do_sync_threshold(struct ctl_table *table, int write,
                       void *buffer, size_t *lenp, loff_t *ppos)
 {
+       struct netns_ipvs *ipvs = table->extra2;
        int *valp = table->data;
        int val[2];
        int rc;
@@ -1885,6 +1886,7 @@ proc_do_sync_threshold(struct ctl_table *table, int write,
                .mode = table->mode,
        };
 
+       mutex_lock(&ipvs->sync_mutex);
        memcpy(val, valp, sizeof(val));
        rc = proc_dointvec(&tmp, write, buffer, lenp, ppos);
        if (write) {
@@ -1894,6 +1896,7 @@ proc_do_sync_threshold(struct ctl_table *table, int write,
                else
                        memcpy(valp, val, sizeof(val));
        }
+       mutex_unlock(&ipvs->sync_mutex);
        return rc;
 }
 
@@ -4321,6 +4324,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct netns_ipvs *ipvs)
        ipvs->sysctl_sync_threshold[0] = DEFAULT_SYNC_THRESHOLD;
        ipvs->sysctl_sync_threshold[1] = DEFAULT_SYNC_PERIOD;
        tbl[idx].data = &ipvs->sysctl_sync_threshold;
+       tbl[idx].extra2 = ipvs;
        tbl[idx++].maxlen = sizeof(ipvs->sysctl_sync_threshold);
        ipvs->sysctl_sync_refresh_period = DEFAULT_SYNC_REFRESH_PERIOD;
        tbl[idx++].data = &ipvs->sysctl_sync_refresh_period;
index 91eacc9b0b9873a387f851a13cbd85f6862fa529..b6bcc8f2f46b7dc0c93e4e75ac9122809fc54be2 100644 (file)
@@ -49,8 +49,8 @@ static const unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] = {
        [SCTP_CONNTRACK_COOKIE_WAIT]            = 3 SECS,
        [SCTP_CONNTRACK_COOKIE_ECHOED]          = 3 SECS,
        [SCTP_CONNTRACK_ESTABLISHED]            = 210 SECS,
-       [SCTP_CONNTRACK_SHUTDOWN_SENT]          = 300 SECS / 1000,
-       [SCTP_CONNTRACK_SHUTDOWN_RECD]          = 300 SECS / 1000,
+       [SCTP_CONNTRACK_SHUTDOWN_SENT]          = 3 SECS,
+       [SCTP_CONNTRACK_SHUTDOWN_RECD]          = 3 SECS,
        [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT]      = 3 SECS,
        [SCTP_CONNTRACK_HEARTBEAT_SENT]         = 30 SECS,
 };
@@ -105,7 +105,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = {
        {
 /*     ORIGINAL        */
 /*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS */
-/* init         */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCW},
+/* init         */ {sCL, sCL, sCW, sCE, sES, sCL, sCL, sSA, sCW},
 /* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},
 /* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
 /* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL},
index d3c6ecd1f5a680bd4ea17cf2ac1601d1d3d2867f..3e841e45f2c07e6f3a8105aa7c167ffae760015a 100644 (file)
@@ -31,7 +31,9 @@ static LIST_HEAD(nf_tables_expressions);
 static LIST_HEAD(nf_tables_objects);
 static LIST_HEAD(nf_tables_flowtables);
 static LIST_HEAD(nf_tables_destroy_list);
+static LIST_HEAD(nf_tables_gc_list);
 static DEFINE_SPINLOCK(nf_tables_destroy_list_lock);
+static DEFINE_SPINLOCK(nf_tables_gc_list_lock);
 
 enum {
        NFT_VALIDATE_SKIP       = 0,
@@ -120,6 +122,9 @@ static void nft_validate_state_update(struct nft_table *table, u8 new_validate_s
 static void nf_tables_trans_destroy_work(struct work_struct *w);
 static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work);
 
+static void nft_trans_gc_work(struct work_struct *work);
+static DECLARE_WORK(trans_gc_work, nft_trans_gc_work);
+
 static void nft_ctx_init(struct nft_ctx *ctx,
                         struct net *net,
                         const struct sk_buff *skb,
@@ -582,10 +587,6 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
        return __nft_trans_set_add(ctx, msg_type, set, NULL);
 }
 
-static void nft_setelem_data_deactivate(const struct net *net,
-                                       const struct nft_set *set,
-                                       struct nft_set_elem *elem);
-
 static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
                                  struct nft_set *set,
                                  const struct nft_set_iter *iter,
@@ -5055,6 +5056,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
 
        INIT_LIST_HEAD(&set->bindings);
        INIT_LIST_HEAD(&set->catchall_list);
+       refcount_set(&set->refs, 1);
        set->table = table;
        write_pnet(&set->net, net);
        set->ops = ops;
@@ -5122,6 +5124,14 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
        }
 }
 
+static void nft_set_put(struct nft_set *set)
+{
+       if (refcount_dec_and_test(&set->refs)) {
+               kfree(set->name);
+               kvfree(set);
+       }
+}
+
 static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
 {
        int i;
@@ -5134,8 +5144,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
 
        set->ops->destroy(ctx, set);
        nft_set_catchall_destroy(ctx, set);
-       kfree(set->name);
-       kvfree(set);
+       nft_set_put(set);
 }
 
 static int nf_tables_delset(struct sk_buff *skb, const struct nfnl_info *info,
@@ -5602,8 +5611,12 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
                                  const struct nft_set_iter *iter,
                                  struct nft_set_elem *elem)
 {
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
        struct nft_set_dump_args *args;
 
+       if (nft_set_elem_expired(ext))
+               return 0;
+
        args = container_of(iter, struct nft_set_dump_args, iter);
        return nf_tables_fill_setelem(args->skb, set, elem, args->reset);
 }
@@ -6274,7 +6287,8 @@ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
        list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
                ext = nft_set_elem_ext(set, catchall->elem);
                if (nft_set_elem_active(ext, genmask) &&
-                   !nft_set_elem_expired(ext))
+                   !nft_set_elem_expired(ext) &&
+                   !nft_set_elem_is_dead(ext))
                        return ext;
        }
 
@@ -6282,29 +6296,6 @@ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
 }
 EXPORT_SYMBOL_GPL(nft_set_catchall_lookup);
 
-void *nft_set_catchall_gc(const struct nft_set *set)
-{
-       struct nft_set_elem_catchall *catchall, *next;
-       struct nft_set_ext *ext;
-       void *elem = NULL;
-
-       list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
-               ext = nft_set_elem_ext(set, catchall->elem);
-
-               if (!nft_set_elem_expired(ext) ||
-                   nft_set_elem_mark_busy(ext))
-                       continue;
-
-               elem = catchall->elem;
-               list_del_rcu(&catchall->list);
-               kfree_rcu(catchall, rcu);
-               break;
-       }
-
-       return elem;
-}
-EXPORT_SYMBOL_GPL(nft_set_catchall_gc);
-
 static int nft_setelem_catchall_insert(const struct net *net,
                                       struct nft_set *set,
                                       const struct nft_set_elem *elem,
@@ -6366,7 +6357,6 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set,
 
        if (nft_setelem_is_catchall(set, elem)) {
                nft_set_elem_change_active(net, set, ext);
-               nft_set_elem_clear_busy(ext);
        } else {
                set->ops->activate(net, set, elem);
        }
@@ -6381,8 +6371,7 @@ static int nft_setelem_catchall_deactivate(const struct net *net,
 
        list_for_each_entry(catchall, &set->catchall_list, list) {
                ext = nft_set_elem_ext(set, catchall->elem);
-               if (!nft_is_active(net, ext) ||
-                   nft_set_elem_mark_busy(ext))
+               if (!nft_is_active(net, ext))
                        continue;
 
                kfree(elem->priv);
@@ -6777,7 +6766,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
                goto err_elem_free;
        }
 
-       ext->genmask = nft_genmask_cur(ctx->net) | NFT_SET_ELEM_BUSY_MASK;
+       ext->genmask = nft_genmask_cur(ctx->net);
 
        err = nft_setelem_insert(ctx->net, set, &elem, &ext2, flags);
        if (err) {
@@ -6929,9 +6918,9 @@ static void nft_setelem_data_activate(const struct net *net,
                nft_use_inc_restore(&(*nft_set_ext_obj(ext))->use);
 }
 
-static void nft_setelem_data_deactivate(const struct net *net,
-                                       const struct nft_set *set,
-                                       struct nft_set_elem *elem)
+void nft_setelem_data_deactivate(const struct net *net,
+                                const struct nft_set *set,
+                                struct nft_set_elem *elem)
 {
        const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
 
@@ -7095,14 +7084,14 @@ static int nft_set_catchall_flush(const struct nft_ctx *ctx,
 
        list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
                ext = nft_set_elem_ext(set, catchall->elem);
-               if (!nft_set_elem_active(ext, genmask) ||
-                   nft_set_elem_mark_busy(ext))
+               if (!nft_set_elem_active(ext, genmask))
                        continue;
 
                elem.priv = catchall->elem;
                ret = __nft_set_catchall_flush(ctx, set, &elem);
                if (ret < 0)
                        break;
+               nft_set_elem_change_active(ctx->net, set, ext);
        }
 
        return ret;
@@ -7170,29 +7159,6 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
        return err;
 }
 
-void nft_set_gc_batch_release(struct rcu_head *rcu)
-{
-       struct nft_set_gc_batch *gcb;
-       unsigned int i;
-
-       gcb = container_of(rcu, struct nft_set_gc_batch, head.rcu);
-       for (i = 0; i < gcb->head.cnt; i++)
-               nft_set_elem_destroy(gcb->head.set, gcb->elems[i], true);
-       kfree(gcb);
-}
-
-struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
-                                               gfp_t gfp)
-{
-       struct nft_set_gc_batch *gcb;
-
-       gcb = kzalloc(sizeof(*gcb), gfp);
-       if (gcb == NULL)
-               return gcb;
-       gcb->head.set = set;
-       return gcb;
-}
-
 /*
  * Stateful objects
  */
@@ -9414,6 +9380,212 @@ void nft_chain_del(struct nft_chain *chain)
        list_del_rcu(&chain->list);
 }
 
+static void nft_trans_gc_setelem_remove(struct nft_ctx *ctx,
+                                       struct nft_trans_gc *trans)
+{
+       void **priv = trans->priv;
+       unsigned int i;
+
+       for (i = 0; i < trans->count; i++) {
+               struct nft_set_elem elem = {
+                       .priv = priv[i],
+               };
+
+               nft_setelem_data_deactivate(ctx->net, trans->set, &elem);
+               nft_setelem_remove(ctx->net, trans->set, &elem);
+       }
+}
+
+void nft_trans_gc_destroy(struct nft_trans_gc *trans)
+{
+       nft_set_put(trans->set);
+       put_net(trans->net);
+       kfree(trans);
+}
+
+static void nft_trans_gc_trans_free(struct rcu_head *rcu)
+{
+       struct nft_set_elem elem = {};
+       struct nft_trans_gc *trans;
+       struct nft_ctx ctx = {};
+       unsigned int i;
+
+       trans = container_of(rcu, struct nft_trans_gc, rcu);
+       ctx.net = read_pnet(&trans->set->net);
+
+       for (i = 0; i < trans->count; i++) {
+               elem.priv = trans->priv[i];
+               if (!nft_setelem_is_catchall(trans->set, &elem))
+                       atomic_dec(&trans->set->nelems);
+
+               nf_tables_set_elem_destroy(&ctx, trans->set, elem.priv);
+       }
+
+       nft_trans_gc_destroy(trans);
+}
+
+static bool nft_trans_gc_work_done(struct nft_trans_gc *trans)
+{
+       struct nftables_pernet *nft_net;
+       struct nft_ctx ctx = {};
+
+       nft_net = nft_pernet(trans->net);
+
+       mutex_lock(&nft_net->commit_mutex);
+
+       /* Check for race with transaction, otherwise this batch refers to
+        * stale objects that might not be there anymore. Skip transaction if
+        * set has been destroyed from control plane transaction in case gc
+        * worker loses race.
+        */
+       if (READ_ONCE(nft_net->gc_seq) != trans->seq || trans->set->dead) {
+               mutex_unlock(&nft_net->commit_mutex);
+               return false;
+       }
+
+       ctx.net = trans->net;
+       ctx.table = trans->set->table;
+
+       nft_trans_gc_setelem_remove(&ctx, trans);
+       mutex_unlock(&nft_net->commit_mutex);
+
+       return true;
+}
+
+static void nft_trans_gc_work(struct work_struct *work)
+{
+       struct nft_trans_gc *trans, *next;
+       LIST_HEAD(trans_gc_list);
+
+       spin_lock(&nf_tables_destroy_list_lock);
+       list_splice_init(&nf_tables_gc_list, &trans_gc_list);
+       spin_unlock(&nf_tables_destroy_list_lock);
+
+       list_for_each_entry_safe(trans, next, &trans_gc_list, list) {
+               list_del(&trans->list);
+               if (!nft_trans_gc_work_done(trans)) {
+                       nft_trans_gc_destroy(trans);
+                       continue;
+               }
+               call_rcu(&trans->rcu, nft_trans_gc_trans_free);
+       }
+}
+
+struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
+                                       unsigned int gc_seq, gfp_t gfp)
+{
+       struct net *net = read_pnet(&set->net);
+       struct nft_trans_gc *trans;
+
+       trans = kzalloc(sizeof(*trans), gfp);
+       if (!trans)
+               return NULL;
+
+       trans->net = maybe_get_net(net);
+       if (!trans->net) {
+               kfree(trans);
+               return NULL;
+       }
+
+       refcount_inc(&set->refs);
+       trans->set = set;
+       trans->seq = gc_seq;
+
+       return trans;
+}
+
+void nft_trans_gc_elem_add(struct nft_trans_gc *trans, void *priv)
+{
+       trans->priv[trans->count++] = priv;
+}
+
+static void nft_trans_gc_queue_work(struct nft_trans_gc *trans)
+{
+       spin_lock(&nf_tables_gc_list_lock);
+       list_add_tail(&trans->list, &nf_tables_gc_list);
+       spin_unlock(&nf_tables_gc_list_lock);
+
+       schedule_work(&trans_gc_work);
+}
+
+static int nft_trans_gc_space(struct nft_trans_gc *trans)
+{
+       return NFT_TRANS_GC_BATCHCOUNT - trans->count;
+}
+
+struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
+                                             unsigned int gc_seq, gfp_t gfp)
+{
+       if (nft_trans_gc_space(gc))
+               return gc;
+
+       nft_trans_gc_queue_work(gc);
+
+       return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
+}
+
+void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans)
+{
+       if (trans->count == 0) {
+               nft_trans_gc_destroy(trans);
+               return;
+       }
+
+       nft_trans_gc_queue_work(trans);
+}
+
+struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp)
+{
+       if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net)))
+               return NULL;
+
+       if (nft_trans_gc_space(gc))
+               return gc;
+
+       call_rcu(&gc->rcu, nft_trans_gc_trans_free);
+
+       return nft_trans_gc_alloc(gc->set, 0, gfp);
+}
+
+void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
+{
+       WARN_ON_ONCE(!lockdep_commit_lock_is_held(trans->net));
+
+       if (trans->count == 0) {
+               nft_trans_gc_destroy(trans);
+               return;
+       }
+
+       call_rcu(&trans->rcu, nft_trans_gc_trans_free);
+}
+
+struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
+                                          unsigned int gc_seq)
+{
+       struct nft_set_elem_catchall *catchall;
+       const struct nft_set *set = gc->set;
+       struct nft_set_ext *ext;
+
+       list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
+               ext = nft_set_elem_ext(set, catchall->elem);
+
+               if (!nft_set_elem_expired(ext))
+                       continue;
+               if (nft_set_elem_is_dead(ext))
+                       goto dead_elem;
+
+               nft_set_elem_dead(ext);
+dead_elem:
+               gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
+               if (!gc)
+                       return NULL;
+
+               nft_trans_gc_elem_add(gc, catchall->elem);
+       }
+
+       return gc;
+}
+
 static void nf_tables_module_autoload_cleanup(struct net *net)
 {
        struct nftables_pernet *nft_net = nft_pernet(net);
@@ -9572,15 +9744,31 @@ static void nft_set_commit_update(struct list_head *set_update_list)
        }
 }
 
+static unsigned int nft_gc_seq_begin(struct nftables_pernet *nft_net)
+{
+       unsigned int gc_seq;
+
+       /* Bump gc counter, it becomes odd, this is the busy mark. */
+       gc_seq = READ_ONCE(nft_net->gc_seq);
+       WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
+
+       return gc_seq;
+}
+
+static void nft_gc_seq_end(struct nftables_pernet *nft_net, unsigned int gc_seq)
+{
+       WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
+}
+
 static int nf_tables_commit(struct net *net, struct sk_buff *skb)
 {
        struct nftables_pernet *nft_net = nft_pernet(net);
        struct nft_trans *trans, *next;
+       unsigned int base_seq, gc_seq;
        LIST_HEAD(set_update_list);
        struct nft_trans_elem *te;
        struct nft_chain *chain;
        struct nft_table *table;
-       unsigned int base_seq;
        LIST_HEAD(adl);
        int err;
 
@@ -9657,6 +9845,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
 
        WRITE_ONCE(nft_net->base_seq, base_seq);
 
+       gc_seq = nft_gc_seq_begin(nft_net);
+
        /* step 3. Start new generation, rules_gen_X now in use. */
        net->nft.gencursor = nft_gencursor_next(net);
 
@@ -9764,6 +9954,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
                        break;
                case NFT_MSG_DELSET:
                case NFT_MSG_DESTROYSET:
+                       nft_trans_set(trans)->dead = 1;
                        list_del_rcu(&nft_trans_set(trans)->list);
                        nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
                                             trans->msg_type, GFP_KERNEL);
@@ -9866,6 +10057,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
        nft_commit_notify(net, NETLINK_CB(skb).portid);
        nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
        nf_tables_commit_audit_log(&adl, nft_net->base_seq);
+
+       nft_gc_seq_end(nft_net, gc_seq);
        nf_tables_commit_release(net);
 
        return 0;
@@ -10866,6 +11059,7 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
        struct net *net = n->net;
        unsigned int deleted;
        bool restart = false;
+       unsigned int gc_seq;
 
        if (event != NETLINK_URELEASE || n->protocol != NETLINK_NETFILTER)
                return NOTIFY_DONE;
@@ -10873,6 +11067,9 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
        nft_net = nft_pernet(net);
        deleted = 0;
        mutex_lock(&nft_net->commit_mutex);
+
+       gc_seq = nft_gc_seq_begin(nft_net);
+
        if (!list_empty(&nf_tables_destroy_list))
                rcu_barrier();
 again:
@@ -10895,6 +11092,8 @@ again:
                if (restart)
                        goto again;
        }
+       nft_gc_seq_end(nft_net, gc_seq);
+
        mutex_unlock(&nft_net->commit_mutex);
 
        return NOTIFY_DONE;
@@ -10915,6 +11114,7 @@ static int __net_init nf_tables_init_net(struct net *net)
        INIT_LIST_HEAD(&nft_net->notify_list);
        mutex_init(&nft_net->commit_mutex);
        nft_net->base_seq = 1;
+       nft_net->gc_seq = 0;
 
        return 0;
 }
@@ -10931,22 +11131,36 @@ static void __net_exit nf_tables_pre_exit_net(struct net *net)
 static void __net_exit nf_tables_exit_net(struct net *net)
 {
        struct nftables_pernet *nft_net = nft_pernet(net);
+       unsigned int gc_seq;
 
        mutex_lock(&nft_net->commit_mutex);
+
+       gc_seq = nft_gc_seq_begin(nft_net);
+
        if (!list_empty(&nft_net->commit_list) ||
            !list_empty(&nft_net->module_list))
                __nf_tables_abort(net, NFNL_ABORT_NONE);
+
        __nft_release_tables(net);
+
+       nft_gc_seq_end(nft_net, gc_seq);
+
        mutex_unlock(&nft_net->commit_mutex);
        WARN_ON_ONCE(!list_empty(&nft_net->tables));
        WARN_ON_ONCE(!list_empty(&nft_net->module_list));
        WARN_ON_ONCE(!list_empty(&nft_net->notify_list));
 }
 
+static void nf_tables_exit_batch(struct list_head *net_exit_list)
+{
+       flush_work(&trans_gc_work);
+}
+
 static struct pernet_operations nf_tables_net_ops = {
        .init           = nf_tables_init_net,
        .pre_exit       = nf_tables_pre_exit_net,
        .exit           = nf_tables_exit_net,
+       .exit_batch     = nf_tables_exit_batch,
        .id             = &nf_tables_net_id,
        .size           = sizeof(struct nftables_pernet),
 };
@@ -11018,6 +11232,7 @@ static void __exit nf_tables_module_exit(void)
        nft_chain_filter_fini();
        nft_chain_route_fini();
        unregister_pernet_subsys(&nf_tables_net_ops);
+       cancel_work_sync(&trans_gc_work);
        cancel_work_sync(&trans_destroy_work);
        rcu_barrier();
        rhltable_destroy(&nft_objname_ht);
index 4fb34d76dbeaffa93629b8147e5a4750dd31ead5..5c5cc01c73c5a7eb1c68fddddc88c8491b3133f6 100644 (file)
@@ -191,6 +191,9 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
        if (IS_ERR(set))
                return PTR_ERR(set);
 
+       if (set->flags & NFT_SET_OBJECT)
+               return -EOPNOTSUPP;
+
        if (set->ops->update == NULL)
                return -EOPNOTSUPP;
 
index 0b73cb0e752f706f44855105515aa195b1e4403d..cef5df84600095079f003adff53de8911d6db9ba 100644 (file)
@@ -59,6 +59,8 @@ static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg,
 
        if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen))
                return 1;
+       if (nft_set_elem_is_dead(&he->ext))
+               return 1;
        if (nft_set_elem_expired(&he->ext))
                return 1;
        if (!nft_set_elem_active(&he->ext, x->genmask))
@@ -188,7 +190,6 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set,
        struct nft_rhash_elem *he = elem->priv;
 
        nft_set_elem_change_active(net, set, &he->ext);
-       nft_set_elem_clear_busy(&he->ext);
 }
 
 static bool nft_rhash_flush(const struct net *net,
@@ -196,12 +197,9 @@ static bool nft_rhash_flush(const struct net *net,
 {
        struct nft_rhash_elem *he = priv;
 
-       if (!nft_set_elem_mark_busy(&he->ext) ||
-           !nft_is_active(net, &he->ext)) {
-               nft_set_elem_change_active(net, set, &he->ext);
-               return true;
-       }
-       return false;
+       nft_set_elem_change_active(net, set, &he->ext);
+
+       return true;
 }
 
 static void *nft_rhash_deactivate(const struct net *net,
@@ -218,9 +216,8 @@ static void *nft_rhash_deactivate(const struct net *net,
 
        rcu_read_lock();
        he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
-       if (he != NULL &&
-           !nft_rhash_flush(net, set, he))
-               he = NULL;
+       if (he)
+               nft_set_elem_change_active(net, set, &he->ext);
 
        rcu_read_unlock();
 
@@ -252,7 +249,9 @@ static bool nft_rhash_delete(const struct nft_set *set,
        if (he == NULL)
                return false;
 
-       return rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params) == 0;
+       nft_set_elem_dead(&he->ext);
+
+       return true;
 }
 
 static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
@@ -278,8 +277,6 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
 
                if (iter->count < iter->skip)
                        goto cont;
-               if (nft_set_elem_expired(&he->ext))
-                       goto cont;
                if (!nft_set_elem_active(&he->ext, iter->genmask))
                        goto cont;
 
@@ -314,25 +311,48 @@ static bool nft_rhash_expr_needs_gc_run(const struct nft_set *set,
 
 static void nft_rhash_gc(struct work_struct *work)
 {
+       struct nftables_pernet *nft_net;
        struct nft_set *set;
        struct nft_rhash_elem *he;
        struct nft_rhash *priv;
-       struct nft_set_gc_batch *gcb = NULL;
        struct rhashtable_iter hti;
+       struct nft_trans_gc *gc;
+       struct net *net;
+       u32 gc_seq;
 
        priv = container_of(work, struct nft_rhash, gc_work.work);
        set  = nft_set_container_of(priv);
+       net  = read_pnet(&set->net);
+       nft_net = nft_pernet(net);
+       gc_seq = READ_ONCE(nft_net->gc_seq);
+
+       gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL);
+       if (!gc)
+               goto done;
 
        rhashtable_walk_enter(&priv->ht, &hti);
        rhashtable_walk_start(&hti);
 
        while ((he = rhashtable_walk_next(&hti))) {
                if (IS_ERR(he)) {
-                       if (PTR_ERR(he) != -EAGAIN)
-                               break;
+                       if (PTR_ERR(he) != -EAGAIN) {
+                               nft_trans_gc_destroy(gc);
+                               gc = NULL;
+                               goto try_later;
+                       }
                        continue;
                }
 
+               /* Ruleset has been updated, try later. */
+               if (READ_ONCE(nft_net->gc_seq) != gc_seq) {
+                       nft_trans_gc_destroy(gc);
+                       gc = NULL;
+                       goto try_later;
+               }
+
+               if (nft_set_elem_is_dead(&he->ext))
+                       goto dead_elem;
+
                if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPRESSIONS) &&
                    nft_rhash_expr_needs_gc_run(set, &he->ext))
                        goto needs_gc_run;
@@ -340,26 +360,26 @@ static void nft_rhash_gc(struct work_struct *work)
                if (!nft_set_elem_expired(&he->ext))
                        continue;
 needs_gc_run:
-               if (nft_set_elem_mark_busy(&he->ext))
-                       continue;
+               nft_set_elem_dead(&he->ext);
+dead_elem:
+               gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
+               if (!gc)
+                       goto try_later;
 
-               gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
-               if (gcb == NULL)
-                       break;
-               rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params);
-               atomic_dec(&set->nelems);
-               nft_set_gc_batch_add(gcb, he);
+               nft_trans_gc_elem_add(gc, he);
        }
+
+       gc = nft_trans_gc_catchall(gc, gc_seq);
+
+try_later:
+       /* catchall list iteration requires rcu read side lock. */
        rhashtable_walk_stop(&hti);
        rhashtable_walk_exit(&hti);
 
-       he = nft_set_catchall_gc(set);
-       if (he) {
-               gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
-               if (gcb)
-                       nft_set_gc_batch_add(gcb, he);
-       }
-       nft_set_gc_batch_complete(gcb);
+       if (gc)
+               nft_trans_gc_queue_async_done(gc);
+
+done:
        queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
                           nft_set_gc_interval(set));
 }
@@ -394,7 +414,7 @@ static int nft_rhash_init(const struct nft_set *set,
                return err;
 
        INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc);
-       if (set->flags & NFT_SET_TIMEOUT)
+       if (set->flags & (NFT_SET_TIMEOUT | NFT_SET_EVAL))
                nft_rhash_gc_init(set);
 
        return 0;
@@ -422,7 +442,6 @@ static void nft_rhash_destroy(const struct nft_ctx *ctx,
        };
 
        cancel_delayed_work_sync(&priv->gc_work);
-       rcu_barrier();
        rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
                                    (void *)&rhash_ctx);
 }
index 49915a2a58eb77be2f666102a8320ecd1b0f44bd..3757fcc55723f635c8d6c4b863f9fe970786afc1 100644 (file)
@@ -566,8 +566,9 @@ next_match:
                        goto out;
 
                if (last) {
-                       if (nft_set_elem_expired(&f->mt[b].e->ext) ||
-                           (genmask &&
+                       if (nft_set_elem_expired(&f->mt[b].e->ext))
+                               goto next_match;
+                       if ((genmask &&
                             !nft_set_elem_active(&f->mt[b].e->ext, genmask)))
                                goto next_match;
 
@@ -602,7 +603,7 @@ static void *nft_pipapo_get(const struct net *net, const struct nft_set *set,
                            const struct nft_set_elem *elem, unsigned int flags)
 {
        return pipapo_get(net, set, (const u8 *)elem->key.val.data,
-                         nft_genmask_cur(net));
+                        nft_genmask_cur(net));
 }
 
 /**
@@ -1528,16 +1529,34 @@ static void pipapo_drop(struct nft_pipapo_match *m,
        }
 }
 
+static void nft_pipapo_gc_deactivate(struct net *net, struct nft_set *set,
+                                    struct nft_pipapo_elem *e)
+
+{
+       struct nft_set_elem elem = {
+               .priv   = e,
+       };
+
+       nft_setelem_data_deactivate(net, set, &elem);
+}
+
 /**
  * pipapo_gc() - Drop expired entries from set, destroy start and end elements
- * @set:       nftables API set representation
+ * @_set:      nftables API set representation
  * @m:         Matching data
  */
-static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
+static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
 {
+       struct nft_set *set = (struct nft_set *) _set;
        struct nft_pipapo *priv = nft_set_priv(set);
+       struct net *net = read_pnet(&set->net);
        int rules_f0, first_rule = 0;
        struct nft_pipapo_elem *e;
+       struct nft_trans_gc *gc;
+
+       gc = nft_trans_gc_alloc(set, 0, GFP_KERNEL);
+       if (!gc)
+               return;
 
        while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {
                union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
@@ -1561,13 +1580,20 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
                f--;
                i--;
                e = f->mt[rulemap[i].to].e;
-               if (nft_set_elem_expired(&e->ext) &&
-                   !nft_set_elem_mark_busy(&e->ext)) {
+
+               /* synchronous gc never fails, there is no need to set on
+                * NFT_SET_ELEM_DEAD_BIT.
+                */
+               if (nft_set_elem_expired(&e->ext)) {
                        priv->dirty = true;
-                       pipapo_drop(m, rulemap);
 
-                       rcu_barrier();
-                       nft_set_elem_destroy(set, e, true);
+                       gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
+                       if (!gc)
+                               break;
+
+                       nft_pipapo_gc_deactivate(net, set, e);
+                       pipapo_drop(m, rulemap);
+                       nft_trans_gc_elem_add(gc, e);
 
                        /* And check again current first rule, which is now the
                         * first we haven't checked.
@@ -1577,11 +1603,11 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
                }
        }
 
-       e = nft_set_catchall_gc(set);
-       if (e)
-               nft_set_elem_destroy(set, e, true);
-
-       priv->last_gc = jiffies;
+       gc = nft_trans_gc_catchall(gc, 0);
+       if (gc) {
+               nft_trans_gc_queue_sync_done(gc);
+               priv->last_gc = jiffies;
+       }
 }
 
 /**
@@ -1664,6 +1690,17 @@ static void nft_pipapo_commit(const struct nft_set *set)
        priv->clone = new_clone;
 }
 
+static bool nft_pipapo_transaction_mutex_held(const struct nft_set *set)
+{
+#ifdef CONFIG_PROVE_LOCKING
+       const struct net *net = read_pnet(&set->net);
+
+       return lockdep_is_held(&nft_pernet(net)->commit_mutex);
+#else
+       return true;
+#endif
+}
+
 static void nft_pipapo_abort(const struct nft_set *set)
 {
        struct nft_pipapo *priv = nft_set_priv(set);
@@ -1672,7 +1709,7 @@ static void nft_pipapo_abort(const struct nft_set *set)
        if (!priv->dirty)
                return;
 
-       m = rcu_dereference(priv->match);
+       m = rcu_dereference_protected(priv->match, nft_pipapo_transaction_mutex_held(set));
 
        new_clone = pipapo_clone(m);
        if (IS_ERR(new_clone))
@@ -1699,14 +1736,9 @@ static void nft_pipapo_activate(const struct net *net,
                                const struct nft_set *set,
                                const struct nft_set_elem *elem)
 {
-       struct nft_pipapo_elem *e;
-
-       e = pipapo_get(net, set, (const u8 *)elem->key.val.data, 0);
-       if (IS_ERR(e))
-               return;
+       struct nft_pipapo_elem *e = elem->priv;
 
        nft_set_elem_change_active(net, set, &e->ext);
-       nft_set_elem_clear_busy(&e->ext);
 }
 
 /**
@@ -1918,10 +1950,6 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
 
        data = (const u8 *)nft_set_ext_key(&e->ext);
 
-       e = pipapo_get(net, set, data, 0);
-       if (IS_ERR(e))
-               return;
-
        while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {
                union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
                const u8 *match_start, *match_end;
@@ -2005,8 +2033,6 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
                        goto cont;
 
                e = f->mt[r].e;
-               if (nft_set_elem_expired(&e->ext))
-                       goto cont;
 
                elem.priv = e;
 
index 8d73fffd2d09da33b27dd704046ed5a16c7538bf..f9d4c8fcbbf82745907920032d15b803ae5561bc 100644 (file)
@@ -46,6 +46,12 @@ static int nft_rbtree_cmp(const struct nft_set *set,
                      set->klen);
 }
 
+static bool nft_rbtree_elem_expired(const struct nft_rbtree_elem *rbe)
+{
+       return nft_set_elem_expired(&rbe->ext) ||
+              nft_set_elem_is_dead(&rbe->ext);
+}
+
 static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
                                const u32 *key, const struct nft_set_ext **ext,
                                unsigned int seq)
@@ -80,7 +86,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
                                continue;
                        }
 
-                       if (nft_set_elem_expired(&rbe->ext))
+                       if (nft_rbtree_elem_expired(rbe))
                                return false;
 
                        if (nft_rbtree_interval_end(rbe)) {
@@ -98,7 +104,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
 
        if (set->flags & NFT_SET_INTERVAL && interval != NULL &&
            nft_set_elem_active(&interval->ext, genmask) &&
-           !nft_set_elem_expired(&interval->ext) &&
+           !nft_rbtree_elem_expired(interval) &&
            nft_rbtree_interval_start(interval)) {
                *ext = &interval->ext;
                return true;
@@ -215,6 +221,18 @@ static void *nft_rbtree_get(const struct net *net, const struct nft_set *set,
        return rbe;
 }
 
+static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set,
+                                struct nft_rbtree *priv,
+                                struct nft_rbtree_elem *rbe)
+{
+       struct nft_set_elem elem = {
+               .priv   = rbe,
+       };
+
+       nft_setelem_data_deactivate(net, set, &elem);
+       rb_erase(&rbe->node, &priv->root);
+}
+
 static int nft_rbtree_gc_elem(const struct nft_set *__set,
                              struct nft_rbtree *priv,
                              struct nft_rbtree_elem *rbe,
@@ -222,11 +240,12 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
 {
        struct nft_set *set = (struct nft_set *)__set;
        struct rb_node *prev = rb_prev(&rbe->node);
+       struct net *net = read_pnet(&set->net);
        struct nft_rbtree_elem *rbe_prev;
-       struct nft_set_gc_batch *gcb;
+       struct nft_trans_gc *gc;
 
-       gcb = nft_set_gc_batch_check(set, NULL, GFP_ATOMIC);
-       if (!gcb)
+       gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC);
+       if (!gc)
                return -ENOMEM;
 
        /* search for end interval coming before this element.
@@ -244,17 +263,28 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
 
        if (prev) {
                rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
+               nft_rbtree_gc_remove(net, set, priv, rbe_prev);
 
-               rb_erase(&rbe_prev->node, &priv->root);
-               atomic_dec(&set->nelems);
-               nft_set_gc_batch_add(gcb, rbe_prev);
+               /* There is always room in this trans gc for this element,
+                * memory allocation never actually happens, hence, the warning
+                * splat in such case. No need to set NFT_SET_ELEM_DEAD_BIT,
+                * this is synchronous gc which never fails.
+                */
+               gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
+               if (WARN_ON_ONCE(!gc))
+                       return -ENOMEM;
+
+               nft_trans_gc_elem_add(gc, rbe_prev);
        }
 
-       rb_erase(&rbe->node, &priv->root);
-       atomic_dec(&set->nelems);
+       nft_rbtree_gc_remove(net, set, priv, rbe);
+       gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
+       if (WARN_ON_ONCE(!gc))
+               return -ENOMEM;
+
+       nft_trans_gc_elem_add(gc, rbe);
 
-       nft_set_gc_batch_add(gcb, rbe);
-       nft_set_gc_batch_complete(gcb);
+       nft_trans_gc_queue_sync_done(gc);
 
        return 0;
 }
@@ -482,7 +512,6 @@ static void nft_rbtree_activate(const struct net *net,
        struct nft_rbtree_elem *rbe = elem->priv;
 
        nft_set_elem_change_active(net, set, &rbe->ext);
-       nft_set_elem_clear_busy(&rbe->ext);
 }
 
 static bool nft_rbtree_flush(const struct net *net,
@@ -490,12 +519,9 @@ static bool nft_rbtree_flush(const struct net *net,
 {
        struct nft_rbtree_elem *rbe = priv;
 
-       if (!nft_set_elem_mark_busy(&rbe->ext) ||
-           !nft_is_active(net, &rbe->ext)) {
-               nft_set_elem_change_active(net, set, &rbe->ext);
-               return true;
-       }
-       return false;
+       nft_set_elem_change_active(net, set, &rbe->ext);
+
+       return true;
 }
 
 static void *nft_rbtree_deactivate(const struct net *net,
@@ -552,8 +578,6 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
 
                if (iter->count < iter->skip)
                        goto cont;
-               if (nft_set_elem_expired(&rbe->ext))
-                       goto cont;
                if (!nft_set_elem_active(&rbe->ext, iter->genmask))
                        goto cont;
 
@@ -572,26 +596,40 @@ cont:
 
 static void nft_rbtree_gc(struct work_struct *work)
 {
-       struct nft_rbtree_elem *rbe, *rbe_end = NULL, *rbe_prev = NULL;
-       struct nft_set_gc_batch *gcb = NULL;
+       struct nft_rbtree_elem *rbe, *rbe_end = NULL;
+       struct nftables_pernet *nft_net;
        struct nft_rbtree *priv;
+       struct nft_trans_gc *gc;
        struct rb_node *node;
        struct nft_set *set;
+       unsigned int gc_seq;
        struct net *net;
-       u8 genmask;
 
        priv = container_of(work, struct nft_rbtree, gc_work.work);
        set  = nft_set_container_of(priv);
        net  = read_pnet(&set->net);
-       genmask = nft_genmask_cur(net);
+       nft_net = nft_pernet(net);
+       gc_seq  = READ_ONCE(nft_net->gc_seq);
+
+       gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL);
+       if (!gc)
+               goto done;
 
        write_lock_bh(&priv->lock);
        write_seqcount_begin(&priv->count);
        for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
+
+               /* Ruleset has been updated, try later. */
+               if (READ_ONCE(nft_net->gc_seq) != gc_seq) {
+                       nft_trans_gc_destroy(gc);
+                       gc = NULL;
+                       goto try_later;
+               }
+
                rbe = rb_entry(node, struct nft_rbtree_elem, node);
 
-               if (!nft_set_elem_active(&rbe->ext, genmask))
-                       continue;
+               if (nft_set_elem_is_dead(&rbe->ext))
+                       goto dead_elem;
 
                /* elements are reversed in the rbtree for historical reasons,
                 * from highest to lowest value, that is why end element is
@@ -604,46 +642,36 @@ static void nft_rbtree_gc(struct work_struct *work)
                if (!nft_set_elem_expired(&rbe->ext))
                        continue;
 
-               if (nft_set_elem_mark_busy(&rbe->ext)) {
-                       rbe_end = NULL;
+               nft_set_elem_dead(&rbe->ext);
+
+               if (!rbe_end)
                        continue;
-               }
 
-               if (rbe_prev) {
-                       rb_erase(&rbe_prev->node, &priv->root);
-                       rbe_prev = NULL;
-               }
-               gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
-               if (!gcb)
-                       break;
+               nft_set_elem_dead(&rbe_end->ext);
 
-               atomic_dec(&set->nelems);
-               nft_set_gc_batch_add(gcb, rbe);
-               rbe_prev = rbe;
+               gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
+               if (!gc)
+                       goto try_later;
 
-               if (rbe_end) {
-                       atomic_dec(&set->nelems);
-                       nft_set_gc_batch_add(gcb, rbe_end);
-                       rb_erase(&rbe_end->node, &priv->root);
-                       rbe_end = NULL;
-               }
-               node = rb_next(node);
-               if (!node)
-                       break;
+               nft_trans_gc_elem_add(gc, rbe_end);
+               rbe_end = NULL;
+dead_elem:
+               gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
+               if (!gc)
+                       goto try_later;
+
+               nft_trans_gc_elem_add(gc, rbe);
        }
-       if (rbe_prev)
-               rb_erase(&rbe_prev->node, &priv->root);
+
+       gc = nft_trans_gc_catchall(gc, gc_seq);
+
+try_later:
        write_seqcount_end(&priv->count);
        write_unlock_bh(&priv->lock);
 
-       rbe = nft_set_catchall_gc(set);
-       if (rbe) {
-               gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
-               if (gcb)
-                       nft_set_gc_batch_add(gcb, rbe);
-       }
-       nft_set_gc_batch_complete(gcb);
-
+       if (gc)
+               nft_trans_gc_queue_async_done(gc);
+done:
        queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
                           nft_set_gc_interval(set));
 }
index 84def74698b78b77bd95dead1b3ee68d48521d45..9ed85be79452d990ad79ad9a0b31a26bb3f4c6a4 100644 (file)
@@ -107,7 +107,7 @@ static void nft_socket_eval(const struct nft_expr *expr,
                break;
        case NFT_SOCKET_MARK:
                if (sk_fullsock(sk)) {
-                       *dest = sk->sk_mark;
+                       *dest = READ_ONCE(sk->sk_mark);
                } else {
                        regs->verdict.code = NFT_BREAK;
                        return;
index 7013f55f05d1ebca3b13d29934d8f6abc1ef36f0..76e01f292aaff638f8c9c37583bc33b3ea942b65 100644 (file)
@@ -77,7 +77,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
 
                if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
                    transparent && sk_fullsock(sk))
-                       pskb->mark = sk->sk_mark;
+                       pskb->mark = READ_ONCE(sk->sk_mark);
 
                if (sk != skb->sk)
                        sock_gen_put(sk);
@@ -138,7 +138,7 @@ socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
 
                if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
                    transparent && sk_fullsock(sk))
-                       pskb->mark = sk->sk_mark;
+                       pskb->mark = READ_ONCE(sk->sk_mark);
 
                if (sk != skb->sk)
                        sock_gen_put(sk);
index a6d2a0b1aa21eaae6041ec9a9321af2d615a5c38..3d7a91e64c88f3478afd648af987b0238b15aee8 100644 (file)
@@ -1829,7 +1829,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
        parms.port_no = OVSP_LOCAL;
        parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
        parms.desired_ifindex = a[OVS_DP_ATTR_IFINDEX]
-               ? nla_get_u32(a[OVS_DP_ATTR_IFINDEX]) : 0;
+               ? nla_get_s32(a[OVS_DP_ATTR_IFINDEX]) : 0;
 
        /* So far only local changes have been made, now need the lock. */
        ovs_lock();
@@ -2049,7 +2049,7 @@ static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
        [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
        [OVS_DP_ATTR_MASKS_CACHE_SIZE] =  NLA_POLICY_RANGE(NLA_U32, 0,
                PCPU_MIN_UNIT_SIZE / sizeof(struct mask_cache_entry)),
-       [OVS_DP_ATTR_IFINDEX] = {.type = NLA_U32 },
+       [OVS_DP_ATTR_IFINDEX] = NLA_POLICY_MIN(NLA_S32, 0),
 };
 
 static const struct genl_small_ops dp_datapath_genl_ops[] = {
@@ -2302,7 +2302,7 @@ restart:
        parms.port_no = port_no;
        parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID];
        parms.desired_ifindex = a[OVS_VPORT_ATTR_IFINDEX]
-               ? nla_get_u32(a[OVS_VPORT_ATTR_IFINDEX]) : 0;
+               ? nla_get_s32(a[OVS_VPORT_ATTR_IFINDEX]) : 0;
 
        vport = new_vport(&parms);
        err = PTR_ERR(vport);
@@ -2539,7 +2539,7 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
        [OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
        [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_UNSPEC },
        [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
-       [OVS_VPORT_ATTR_IFINDEX] = { .type = NLA_U32 },
+       [OVS_VPORT_ATTR_IFINDEX] = NLA_POLICY_MIN(NLA_S32, 0),
        [OVS_VPORT_ATTR_NETNSID] = { .type = NLA_S32 },
        [OVS_VPORT_ATTR_UPCALL_STATS] = { .type = NLA_NESTED },
 };
index 8e3ddec4c3d57e7492b55404db3119cbba6f6022..a2935bd18ed98356e73d058e7d416fca832b6b6b 100644 (file)
@@ -401,18 +401,20 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
 {
        union tpacket_uhdr h;
 
+       /* WRITE_ONCE() are paired with READ_ONCE() in __packet_get_status */
+
        h.raw = frame;
        switch (po->tp_version) {
        case TPACKET_V1:
-               h.h1->tp_status = status;
+               WRITE_ONCE(h.h1->tp_status, status);
                flush_dcache_page(pgv_to_page(&h.h1->tp_status));
                break;
        case TPACKET_V2:
-               h.h2->tp_status = status;
+               WRITE_ONCE(h.h2->tp_status, status);
                flush_dcache_page(pgv_to_page(&h.h2->tp_status));
                break;
        case TPACKET_V3:
-               h.h3->tp_status = status;
+               WRITE_ONCE(h.h3->tp_status, status);
                flush_dcache_page(pgv_to_page(&h.h3->tp_status));
                break;
        default:
@@ -429,17 +431,19 @@ static int __packet_get_status(const struct packet_sock *po, void *frame)
 
        smp_rmb();
 
+       /* READ_ONCE() are paired with WRITE_ONCE() in __packet_set_status */
+
        h.raw = frame;
        switch (po->tp_version) {
        case TPACKET_V1:
                flush_dcache_page(pgv_to_page(&h.h1->tp_status));
-               return h.h1->tp_status;
+               return READ_ONCE(h.h1->tp_status);
        case TPACKET_V2:
                flush_dcache_page(pgv_to_page(&h.h2->tp_status));
-               return h.h2->tp_status;
+               return READ_ONCE(h.h2->tp_status);
        case TPACKET_V3:
                flush_dcache_page(pgv_to_page(&h.h3->tp_status));
-               return h.h3->tp_status;
+               return READ_ONCE(h.h3->tp_status);
        default:
                WARN(1, "TPACKET version not supported.\n");
                BUG();
@@ -2050,8 +2054,8 @@ retry:
 
        skb->protocol = proto;
        skb->dev = dev;
-       skb->priority = sk->sk_priority;
-       skb->mark = sk->sk_mark;
+       skb->priority = READ_ONCE(sk->sk_priority);
+       skb->mark = READ_ONCE(sk->sk_mark);
        skb->tstamp = sockc.transmit_time;
 
        skb_setup_tx_timestamp(skb, sockc.tsflags);
@@ -2585,8 +2589,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 
        skb->protocol = proto;
        skb->dev = dev;
-       skb->priority = po->sk.sk_priority;
-       skb->mark = po->sk.sk_mark;
+       skb->priority = READ_ONCE(po->sk.sk_priority);
+       skb->mark = READ_ONCE(po->sk.sk_mark);
        skb->tstamp = sockc->transmit_time;
        skb_setup_tx_timestamp(skb, sockc->tsflags);
        skb_zcopy_set_nouarg(skb, ph.raw);
@@ -2988,7 +2992,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                goto out_unlock;
 
        sockcm_init(&sockc, sk);
-       sockc.mark = sk->sk_mark;
+       sockc.mark = READ_ONCE(sk->sk_mark);
        if (msg->msg_controllen) {
                err = sock_cmsg_send(sk, msg, &sockc);
                if (unlikely(err))
@@ -3061,7 +3065,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 
        skb->protocol = proto;
        skb->dev = dev;
-       skb->priority = sk->sk_priority;
+       skb->priority = READ_ONCE(sk->sk_priority);
        skb->mark = sockc.mark;
        skb->tstamp = sockc.transmit_time;
 
index 8da9d039d964ea417700a2f59ad95a9ce52f5eab..9f0711da9c95907cf5c7fdbef74538a59f8b1a36 100644 (file)
@@ -776,7 +776,8 @@ mpls_stack_entry_policy[TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX + 1] = {
        [TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL]    = { .type = NLA_U32 },
 };
 
-static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = {
+static const struct nla_policy
+cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX + 1] = {
        [TCA_FLOWER_KEY_CFM_MD_LEVEL]   = NLA_POLICY_MAX(NLA_U8,
                                                FLOW_DIS_CFM_MDL_MAX),
        [TCA_FLOWER_KEY_CFM_OPCODE]     = { .type = NLA_U8 },
@@ -1709,7 +1710,7 @@ static int fl_set_key_cfm(struct nlattr **tb,
                          struct fl_flow_key *mask,
                          struct netlink_ext_ack *extack)
 {
-       struct nlattr *nla_cfm_opt[TCA_FLOWER_KEY_CFM_OPT_MAX];
+       struct nlattr *nla_cfm_opt[TCA_FLOWER_KEY_CFM_OPT_MAX + 1];
        int err;
 
        if (!tb[TCA_FLOWER_KEY_CFM])
index 8641f805931793a468abb01b7fcd95c8cf9891f4..c49d6af0e04807275229e817759f88e5272364a8 100644 (file)
@@ -267,7 +267,6 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
                        return -ENOBUFS;
 
                fnew->id = f->id;
-               fnew->res = f->res;
                fnew->ifindex = f->ifindex;
                fnew->tp = f->tp;
 
index d0c53724d3e86bce003296950e8d5a71ff8227d2..1e20bbd687f1df483be6952ebdf3b01b7745f1c6 100644 (file)
@@ -513,7 +513,6 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
        if (fold) {
                f->id = fold->id;
                f->iif = fold->iif;
-               f->res = fold->res;
                f->handle = fold->handle;
 
                f->tp = fold->tp;
index 5abf31e432caf711c7c31d2d9ed430eb3d3b3846..da4c179a4d41844e341a2c773d13588e18d76f93 100644 (file)
@@ -826,7 +826,6 @@ static struct tc_u_knode *u32_init_knode(struct net *net, struct tcf_proto *tp,
 
        new->ifindex = n->ifindex;
        new->fshift = n->fshift;
-       new->res = n->res;
        new->flags = n->flags;
        RCU_INIT_POINTER(new->ht_down, ht);
 
@@ -1024,18 +1023,62 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
                return -EINVAL;
        }
 
+       /* At this point, we need to derive the new handle that will be used to
+        * uniquely map the identity of this table match entry. The
+        * identity of the entry that we need to construct is 32 bits made of:
+        *     htid(12b):bucketid(8b):node/entryid(12b)
+        *
+        * At this point _we have the table(ht)_ in which we will insert this
+        * entry. We carry the table's id in variable "htid".
+        * Note that earlier code picked the ht selection either by a) the user
+        * providing the htid specified via TCA_U32_HASH attribute or b) when
+        * no such attribute is passed then the root ht, is default to at ID
+        * 0x[800][00][000]. Rule: the root table has a single bucket with ID 0.
+        * If OTOH the user passed us the htid, they may also pass a bucketid of
+        * choice. 0 is fine. For example a user htid is 0x[600][01][000] it is
+        * indicating hash bucketid of 1. Rule: the entry/node ID _cannot_ be
+        * passed via the htid, so even if it was non-zero it will be ignored.
+        *
+        * We may also have a handle, if the user passed one. The handle also
+        * carries the same addressing of htid(12b):bucketid(8b):node/entryid(12b).
+        * Rule: the bucketid on the handle is ignored even if one was passed;
+        * rather the value on "htid" is always assumed to be the bucketid.
+        */
        if (handle) {
+               /* Rule: The htid from handle and tableid from htid must match */
                if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid)) {
                        NL_SET_ERR_MSG_MOD(extack, "Handle specified hash table address mismatch");
                        return -EINVAL;
                }
-               handle = htid | TC_U32_NODE(handle);
-               err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, handle,
-                                   GFP_KERNEL);
-               if (err)
-                       return err;
-       } else
+               /* Ok, so far we have a valid htid(12b):bucketid(8b) but we
+                * need to finalize the table entry identification with the last
+                * part - the node/entryid(12b)). Rule: Nodeid _cannot be 0_ for
+                * entries. Rule: nodeid of 0 is reserved only for tables(see
+                * earlier code which processes TC_U32_DIVISOR attribute).
+                * Rule: The nodeid can only be derived from the handle (and not
+                * htid).
+                * Rule: if the handle specified zero for the node id example
+                * 0x60000000, then pick a new nodeid from the pool of IDs
+                * this hash table has been allocating from.
+                * If OTOH it is specified (i.e for example the user passed a
+                * handle such as 0x60000123), then we use it generate our final
+                * handle which is used to uniquely identify the match entry.
+                */
+               if (!TC_U32_NODE(handle)) {
+                       handle = gen_new_kid(ht, htid);
+               } else {
+                       handle = htid | TC_U32_NODE(handle);
+                       err = idr_alloc_u32(&ht->handle_idr, NULL, &handle,
+                                           handle, GFP_KERNEL);
+                       if (err)
+                               return err;
+               }
+       } else {
+               /* The user did not give us a handle; lets just generate one
+                * from the table's pool of nodeids.
+                */
                handle = gen_new_kid(ht, htid);
+       }
 
        if (tb[TCA_U32_SEL] == NULL) {
                NL_SET_ERR_MSG_MOD(extack, "Selector not specified");
index af85a73c4c5458ec9b018e5f43f420a3b2079917..6fdba069f6bfd306fa68fc2e68bdcaf0cf4d4e9e 100644 (file)
@@ -568,7 +568,7 @@ META_COLLECTOR(int_sk_rcvtimeo)
                *err = -1;
                return;
        }
-       dst->value = sk->sk_rcvtimeo / HZ;
+       dst->value = READ_ONCE(sk->sk_rcvtimeo) / HZ;
 }
 
 META_COLLECTOR(int_sk_sndtimeo)
@@ -579,7 +579,7 @@ META_COLLECTOR(int_sk_sndtimeo)
                *err = -1;
                return;
        }
-       dst->value = sk->sk_sndtimeo / HZ;
+       dst->value = READ_ONCE(sk->sk_sndtimeo) / HZ;
 }
 
 META_COLLECTOR(int_sk_sendmsg_off)
index 717ae51d94a0ae4f45317e8ba86f51ab4ac41aa6..8c9cfff7fd05c0f83cf2abdd18ecebdf72fb94d7 100644 (file)
@@ -1015,6 +1015,11 @@ static const struct nla_policy taprio_tc_policy[TCA_TAPRIO_TC_ENTRY_MAX + 1] = {
                                                              TC_FP_PREEMPTIBLE),
 };
 
+static struct netlink_range_validation_signed taprio_cycle_time_range = {
+       .min = 0,
+       .max = INT_MAX,
+};
+
 static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
        [TCA_TAPRIO_ATTR_PRIOMAP]              = {
                .len = sizeof(struct tc_mqprio_qopt)
@@ -1023,7 +1028,8 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
        [TCA_TAPRIO_ATTR_SCHED_BASE_TIME]            = { .type = NLA_S64 },
        [TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY]         = { .type = NLA_NESTED },
        [TCA_TAPRIO_ATTR_SCHED_CLOCKID]              = { .type = NLA_S32 },
-       [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]           = { .type = NLA_S64 },
+       [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]           =
+               NLA_POLICY_FULL_RANGE_SIGNED(NLA_S64, &taprio_cycle_time_range),
        [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 },
        [TCA_TAPRIO_ATTR_FLAGS]                      = { .type = NLA_U32 },
        [TCA_TAPRIO_ATTR_TXTIME_DELAY]               = { .type = NLA_U32 },
@@ -1159,6 +1165,11 @@ static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb,
                        return -EINVAL;
                }
 
+               if (cycle < 0 || cycle > INT_MAX) {
+                       NL_SET_ERR_MSG(extack, "'cycle_time' is too big");
+                       return -EINVAL;
+               }
+
                new->cycle_time = cycle;
        }
 
@@ -1347,7 +1358,7 @@ static void setup_txtime(struct taprio_sched *q,
                         struct sched_gate_list *sched, ktime_t base)
 {
        struct sched_entry *entry;
-       u32 interval = 0;
+       u64 interval = 0;
 
        list_for_each_entry(entry, &sched->entries, list) {
                entry->next_txtime = ktime_add_ns(base, interval);
index a7f887d91d89b82d9a799907e67b33cadee24523..f5834af5fad535c420381827548cecdf0d03b0d5 100644 (file)
@@ -378,8 +378,8 @@ static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
        sk->sk_state = SMC_INIT;
        sk->sk_destruct = smc_destruct;
        sk->sk_protocol = protocol;
-       WRITE_ONCE(sk->sk_sndbuf, READ_ONCE(net->smc.sysctl_wmem));
-       WRITE_ONCE(sk->sk_rcvbuf, READ_ONCE(net->smc.sysctl_rmem));
+       WRITE_ONCE(sk->sk_sndbuf, 2 * READ_ONCE(net->smc.sysctl_wmem));
+       WRITE_ONCE(sk->sk_rcvbuf, 2 * READ_ONCE(net->smc.sysctl_rmem));
        smc = smc_sk(sk);
        INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work);
        INIT_WORK(&smc->connect_work, smc_connect_work);
@@ -436,24 +436,9 @@ out:
        return rc;
 }
 
-static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk,
-                                  unsigned long mask)
-{
-       /* options we don't get control via setsockopt for */
-       nsk->sk_type = osk->sk_type;
-       nsk->sk_sndbuf = osk->sk_sndbuf;
-       nsk->sk_rcvbuf = osk->sk_rcvbuf;
-       nsk->sk_sndtimeo = osk->sk_sndtimeo;
-       nsk->sk_rcvtimeo = osk->sk_rcvtimeo;
-       nsk->sk_mark = osk->sk_mark;
-       nsk->sk_priority = osk->sk_priority;
-       nsk->sk_rcvlowat = osk->sk_rcvlowat;
-       nsk->sk_bound_dev_if = osk->sk_bound_dev_if;
-       nsk->sk_err = osk->sk_err;
-
-       nsk->sk_flags &= ~mask;
-       nsk->sk_flags |= osk->sk_flags & mask;
-}
+/* copy only relevant settings and flags of SOL_SOCKET level from smc to
+ * clc socket (since smc is not called for these options from net/core)
+ */
 
 #define SK_FLAGS_SMC_TO_CLC ((1UL << SOCK_URGINLINE) | \
                             (1UL << SOCK_KEEPOPEN) | \
@@ -470,9 +455,55 @@ static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk,
                             (1UL << SOCK_NOFCS) | \
                             (1UL << SOCK_FILTER_LOCKED) | \
                             (1UL << SOCK_TSTAMP_NEW))
-/* copy only relevant settings and flags of SOL_SOCKET level from smc to
- * clc socket (since smc is not called for these options from net/core)
- */
+
+/* if set, use value set by setsockopt() - else use IPv4 or SMC sysctl value */
+static void smc_adjust_sock_bufsizes(struct sock *nsk, struct sock *osk,
+                                    unsigned long mask)
+{
+       struct net *nnet = sock_net(nsk);
+
+       nsk->sk_userlocks = osk->sk_userlocks;
+       if (osk->sk_userlocks & SOCK_SNDBUF_LOCK) {
+               nsk->sk_sndbuf = osk->sk_sndbuf;
+       } else {
+               if (mask == SK_FLAGS_SMC_TO_CLC)
+                       WRITE_ONCE(nsk->sk_sndbuf,
+                                  READ_ONCE(nnet->ipv4.sysctl_tcp_wmem[1]));
+               else
+                       WRITE_ONCE(nsk->sk_sndbuf,
+                                  2 * READ_ONCE(nnet->smc.sysctl_wmem));
+       }
+       if (osk->sk_userlocks & SOCK_RCVBUF_LOCK) {
+               nsk->sk_rcvbuf = osk->sk_rcvbuf;
+       } else {
+               if (mask == SK_FLAGS_SMC_TO_CLC)
+                       WRITE_ONCE(nsk->sk_rcvbuf,
+                                  READ_ONCE(nnet->ipv4.sysctl_tcp_rmem[1]));
+               else
+                       WRITE_ONCE(nsk->sk_rcvbuf,
+                                  2 * READ_ONCE(nnet->smc.sysctl_rmem));
+       }
+}
+
+static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk,
+                                  unsigned long mask)
+{
+       /* options we don't get control via setsockopt for */
+       nsk->sk_type = osk->sk_type;
+       nsk->sk_sndtimeo = osk->sk_sndtimeo;
+       nsk->sk_rcvtimeo = osk->sk_rcvtimeo;
+       nsk->sk_mark = READ_ONCE(osk->sk_mark);
+       nsk->sk_priority = osk->sk_priority;
+       nsk->sk_rcvlowat = osk->sk_rcvlowat;
+       nsk->sk_bound_dev_if = osk->sk_bound_dev_if;
+       nsk->sk_err = osk->sk_err;
+
+       nsk->sk_flags &= ~mask;
+       nsk->sk_flags |= osk->sk_flags & mask;
+
+       smc_adjust_sock_bufsizes(nsk, osk, mask);
+}
+
 static void smc_copy_sock_settings_to_clc(struct smc_sock *smc)
 {
        smc_copy_sock_settings(smc->clcsock->sk, &smc->sk, SK_FLAGS_SMC_TO_CLC);
@@ -2479,8 +2510,6 @@ static void smc_tcp_listen_work(struct work_struct *work)
                sock_hold(lsk); /* sock_put in smc_listen_work */
                INIT_WORK(&new_smc->smc_listen_work, smc_listen_work);
                smc_copy_sock_settings_to_smc(new_smc);
-               new_smc->sk.sk_sndbuf = lsmc->sk.sk_sndbuf;
-               new_smc->sk.sk_rcvbuf = lsmc->sk.sk_rcvbuf;
                sock_hold(&new_smc->sk); /* sock_put in passive closing */
                if (!queue_work(smc_hs_wq, &new_smc->smc_listen_work))
                        sock_put(&new_smc->sk);
index 2eeea4cdc7187eed2a3b12888d8f647382f6f2ac..1f2b912c43d10896369f405f16fe920929bba5d4 100644 (file)
@@ -161,7 +161,7 @@ struct smc_connection {
 
        struct smc_buf_desc     *sndbuf_desc;   /* send buffer descriptor */
        struct smc_buf_desc     *rmb_desc;      /* RMBE descriptor */
-       int                     rmbe_size_short;/* compressed notation */
+       int                     rmbe_size_comp; /* compressed notation */
        int                     rmbe_update_limit;
                                                /* lower limit for consumer
                                                 * cursor update
index b9b8b07aa7023f899a4a8d627f2c809e7c14c0fe..c90d9e5dda540aaf1c3e4b09418d06ab9b260b95 100644 (file)
@@ -1007,7 +1007,7 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
                clc->d0.gid =
                        conn->lgr->smcd->ops->get_local_gid(conn->lgr->smcd);
                clc->d0.token = conn->rmb_desc->token;
-               clc->d0.dmbe_size = conn->rmbe_size_short;
+               clc->d0.dmbe_size = conn->rmbe_size_comp;
                clc->d0.dmbe_idx = 0;
                memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
                if (version == SMC_V1) {
@@ -1050,7 +1050,7 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
                        clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu);
                        break;
                }
-               clc->r0.rmbe_size = conn->rmbe_size_short;
+               clc->r0.rmbe_size = conn->rmbe_size_comp;
                clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ?
                        cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) :
                        cpu_to_be64((u64)sg_dma_address
index 3f465faf2b6814b7e48972bb538bb8c348e62af7..6b78075404d7ddbd3546ca7247c6be1af0d1feaf 100644 (file)
@@ -2309,31 +2309,30 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
        struct smc_connection *conn = &smc->conn;
        struct smc_link_group *lgr = conn->lgr;
        struct list_head *buf_list;
-       int bufsize, bufsize_short;
+       int bufsize, bufsize_comp;
        struct rw_semaphore *lock;      /* lock buffer list */
        bool is_dgraded = false;
-       int sk_buf_size;
 
        if (is_rmb)
                /* use socket recv buffer size (w/o overhead) as start value */
-               sk_buf_size = smc->sk.sk_rcvbuf;
+               bufsize = smc->sk.sk_rcvbuf / 2;
        else
                /* use socket send buffer size (w/o overhead) as start value */
-               sk_buf_size = smc->sk.sk_sndbuf;
+               bufsize = smc->sk.sk_sndbuf / 2;
 
-       for (bufsize_short = smc_compress_bufsize(sk_buf_size, is_smcd, is_rmb);
-            bufsize_short >= 0; bufsize_short--) {
+       for (bufsize_comp = smc_compress_bufsize(bufsize, is_smcd, is_rmb);
+            bufsize_comp >= 0; bufsize_comp--) {
                if (is_rmb) {
                        lock = &lgr->rmbs_lock;
-                       buf_list = &lgr->rmbs[bufsize_short];
+                       buf_list = &lgr->rmbs[bufsize_comp];
                } else {
                        lock = &lgr->sndbufs_lock;
-                       buf_list = &lgr->sndbufs[bufsize_short];
+                       buf_list = &lgr->sndbufs[bufsize_comp];
                }
-               bufsize = smc_uncompress_bufsize(bufsize_short);
+               bufsize = smc_uncompress_bufsize(bufsize_comp);
 
                /* check for reusable slot in the link group */
-               buf_desc = smc_buf_get_slot(bufsize_short, lock, buf_list);
+               buf_desc = smc_buf_get_slot(bufsize_comp, lock, buf_list);
                if (buf_desc) {
                        buf_desc->is_dma_need_sync = 0;
                        SMC_STAT_RMB_SIZE(smc, is_smcd, is_rmb, bufsize);
@@ -2377,8 +2376,8 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
 
        if (is_rmb) {
                conn->rmb_desc = buf_desc;
-               conn->rmbe_size_short = bufsize_short;
-               smc->sk.sk_rcvbuf = bufsize;
+               conn->rmbe_size_comp = bufsize_comp;
+               smc->sk.sk_rcvbuf = bufsize * 2;
                atomic_set(&conn->bytes_to_rcv, 0);
                conn->rmbe_update_limit =
                        smc_rmb_wnd_update_limit(buf_desc->len);
@@ -2386,7 +2385,7 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
                        smc_ism_set_conn(conn); /* map RMB/smcd_dev to conn */
        } else {
                conn->sndbuf_desc = buf_desc;
-               smc->sk.sk_sndbuf = bufsize;
+               smc->sk.sk_sndbuf = bufsize * 2;
                atomic_set(&conn->sndbuf_space, bufsize);
        }
        return 0;
index b6f79fabb9d3f2256af847aff3ff7cf57ec8f4bb..0b2a957ca5f5f09408cc94460fde5e53b5fa4b5d 100644 (file)
 
 static int min_sndbuf = SMC_BUF_MIN_SIZE;
 static int min_rcvbuf = SMC_BUF_MIN_SIZE;
+static int max_sndbuf = INT_MAX / 2;
+static int max_rcvbuf = INT_MAX / 2;
+static const int net_smc_wmem_init = (64 * 1024);
+static const int net_smc_rmem_init = (64 * 1024);
 
 static struct ctl_table smc_table[] = {
        {
@@ -53,6 +57,7 @@ static struct ctl_table smc_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
                .extra1         = &min_sndbuf,
+               .extra2         = &max_sndbuf,
        },
        {
                .procname       = "rmem",
@@ -61,6 +66,7 @@ static struct ctl_table smc_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
                .extra1         = &min_rcvbuf,
+               .extra2         = &max_rcvbuf,
        },
        {  }
 };
@@ -88,8 +94,8 @@ int __net_init smc_sysctl_net_init(struct net *net)
        net->smc.sysctl_autocorking_size = SMC_AUTOCORKING_DEFAULT_SIZE;
        net->smc.sysctl_smcr_buf_type = SMCR_PHYS_CONT_BUFS;
        net->smc.sysctl_smcr_testlink_time = SMC_LLC_TESTLINK_DEFAULT_TIME;
-       WRITE_ONCE(net->smc.sysctl_wmem, READ_ONCE(net->ipv4.sysctl_tcp_wmem[1]));
-       WRITE_ONCE(net->smc.sysctl_rmem, READ_ONCE(net->ipv4.sysctl_tcp_rmem[1]));
+       WRITE_ONCE(net->smc.sysctl_wmem, net_smc_wmem_init);
+       WRITE_ONCE(net->smc.sysctl_rmem, net_smc_rmem_init);
 
        return 0;
 
index e43f2638241149728ff9dce43469609b5fcb8129..2eb8df44f894d7e91240382dfc83fac1b1250dde 100644 (file)
@@ -1244,6 +1244,9 @@ static int svc_tcp_sendmsg(struct socket *sock, struct xdr_buf *xdr,
        if (ret != head->iov_len)
                goto out;
 
+       if (xdr_buf_pagecount(xdr))
+               xdr->bvec[0].bv_offset = offset_in_page(xdr->page_base);
+
        msg.msg_flags = MSG_SPLICE_PAGES;
        iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, xdr->bvec,
                      xdr_buf_pagecount(xdr), xdr->page_len);
index b098fde373abf7a7749db932cd92d9820d3b2fc8..28c0771c4e8c345cac907d31ca3c78d73ac92b03 100644 (file)
@@ -935,9 +935,6 @@ struct rpcrdma_rep *rpcrdma_rep_create(struct rpcrdma_xprt *r_xprt,
        if (!rep->rr_rdmabuf)
                goto out_free;
 
-       if (!rpcrdma_regbuf_dma_map(r_xprt, rep->rr_rdmabuf))
-               goto out_free_regbuf;
-
        rep->rr_cid.ci_completion_id =
                atomic_inc_return(&r_xprt->rx_ep->re_completion_ids);
 
@@ -956,8 +953,6 @@ struct rpcrdma_rep *rpcrdma_rep_create(struct rpcrdma_xprt *r_xprt,
        spin_unlock(&buf->rb_lock);
        return rep;
 
-out_free_regbuf:
-       rpcrdma_regbuf_free(rep->rr_rdmabuf);
 out_free:
        kfree(rep);
 out:
@@ -1363,6 +1358,10 @@ void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp)
                        rep = rpcrdma_rep_create(r_xprt, temp);
                if (!rep)
                        break;
+               if (!rpcrdma_regbuf_dma_map(r_xprt, rep->rr_rdmabuf)) {
+                       rpcrdma_rep_put(buf, rep);
+                       break;
+               }
 
                rep->rr_cid.ci_queue_id = ep->re_attr.recv_cq->res.id;
                trace_xprtrdma_post_recv(rep);
index 2021fe557e5030a420e08741f0408f25b9f8cb89..529101eb20bd5d9b4081b8979d6b3d1f96421553 100644 (file)
@@ -52,6 +52,8 @@ static LIST_HEAD(tls_device_list);
 static LIST_HEAD(tls_device_down_list);
 static DEFINE_SPINLOCK(tls_device_lock);
 
+static struct page *dummy_page;
+
 static void tls_device_free_ctx(struct tls_context *ctx)
 {
        if (ctx->tx_conf == TLS_HW) {
@@ -312,36 +314,33 @@ static int tls_push_record(struct sock *sk,
        return tls_push_sg(sk, ctx, offload_ctx->sg_tx_data, 0, flags);
 }
 
-static int tls_device_record_close(struct sock *sk,
-                                  struct tls_context *ctx,
-                                  struct tls_record_info *record,
-                                  struct page_frag *pfrag,
-                                  unsigned char record_type)
+static void tls_device_record_close(struct sock *sk,
+                                   struct tls_context *ctx,
+                                   struct tls_record_info *record,
+                                   struct page_frag *pfrag,
+                                   unsigned char record_type)
 {
        struct tls_prot_info *prot = &ctx->prot_info;
-       int ret;
+       struct page_frag dummy_tag_frag;
 
        /* append tag
         * device will fill in the tag, we just need to append a placeholder
         * use socket memory to improve coalescing (re-using a single buffer
         * increases frag count)
-        * if we can't allocate memory now, steal some back from data
+        * if we can't allocate memory now use the dummy page
         */
-       if (likely(skb_page_frag_refill(prot->tag_size, pfrag,
-                                       sk->sk_allocation))) {
-               ret = 0;
-               tls_append_frag(record, pfrag, prot->tag_size);
-       } else {
-               ret = prot->tag_size;
-               if (record->len <= prot->overhead_size)
-                       return -ENOMEM;
+       if (unlikely(pfrag->size - pfrag->offset < prot->tag_size) &&
+           !skb_page_frag_refill(prot->tag_size, pfrag, sk->sk_allocation)) {
+               dummy_tag_frag.page = dummy_page;
+               dummy_tag_frag.offset = 0;
+               pfrag = &dummy_tag_frag;
        }
+       tls_append_frag(record, pfrag, prot->tag_size);
 
        /* fill prepend */
        tls_fill_prepend(ctx, skb_frag_address(&record->frags[0]),
                         record->len - prot->overhead_size,
                         record_type);
-       return ret;
 }
 
 static int tls_create_new_record(struct tls_offload_context_tx *offload_ctx,
@@ -541,18 +540,8 @@ last_record:
 
                if (done || record->len >= max_open_record_len ||
                    (record->num_frags >= MAX_SKB_FRAGS - 1)) {
-                       rc = tls_device_record_close(sk, tls_ctx, record,
-                                                    pfrag, record_type);
-                       if (rc) {
-                               if (rc > 0) {
-                                       size += rc;
-                               } else {
-                                       size = orig_size;
-                                       destroy_record(record);
-                                       ctx->open_record = NULL;
-                                       break;
-                               }
-                       }
+                       tls_device_record_close(sk, tls_ctx, record,
+                                               pfrag, record_type);
 
                        rc = tls_push_record(sk,
                                             tls_ctx,
@@ -1450,14 +1439,26 @@ int __init tls_device_init(void)
 {
        int err;
 
-       destruct_wq = alloc_workqueue("ktls_device_destruct", 0, 0);
-       if (!destruct_wq)
+       dummy_page = alloc_page(GFP_KERNEL);
+       if (!dummy_page)
                return -ENOMEM;
 
+       destruct_wq = alloc_workqueue("ktls_device_destruct", 0, 0);
+       if (!destruct_wq) {
+               err = -ENOMEM;
+               goto err_free_dummy;
+       }
+
        err = register_netdevice_notifier(&tls_dev_notifier);
        if (err)
-               destroy_workqueue(destruct_wq);
+               goto err_destroy_wq;
 
+       return 0;
+
+err_destroy_wq:
+       destroy_workqueue(destruct_wq);
+err_free_dummy:
+       put_page(dummy_page);
        return err;
 }
 
@@ -1466,4 +1467,5 @@ void __exit tls_device_cleanup(void)
        unregister_netdevice_notifier(&tls_dev_notifier);
        destroy_workqueue(destruct_wq);
        clean_acked_data_flush();
+       put_page(dummy_page);
 }
index b6896126bb92245eb76a5a1747c92c24d9a58451..4a8ee2f6badb9a1fa3c178e3147ab4f30ed30fca 100644 (file)
@@ -139,9 +139,6 @@ int tls_push_sg(struct sock *sk,
 
        ctx->splicing_pages = true;
        while (1) {
-               if (sg_is_last(sg))
-                       msg.msg_flags = flags;
-
                /* is sending application-limited? */
                tcp_rate_check_app_limited(sk);
                p = sg_page(sg);
index 78585217f61a6944934f1cc0b3b930284e891ed4..86930a8ed012bfad9a407db985782934f52b9698 100644 (file)
@@ -790,7 +790,7 @@ static int unix_set_peek_off(struct sock *sk, int val)
        if (mutex_lock_interruptible(&u->iolock))
                return -EINTR;
 
-       sk->sk_peek_off = val;
+       WRITE_ONCE(sk->sk_peek_off, val);
        mutex_unlock(&u->iolock);
 
        return 0;
index 0da2e6a2a7ea947406b621ab5a88e29540607375..8bcf8e293308e3fe9e731a0195b69fad9b524c84 100644 (file)
@@ -5430,8 +5430,11 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
        if (!wiphy->mbssid_max_interfaces)
                return ERR_PTR(-EINVAL);
 
-       nla_for_each_nested(nl_elems, attrs, rem_elems)
+       nla_for_each_nested(nl_elems, attrs, rem_elems) {
+               if (num_elems >= 255)
+                       return ERR_PTR(-EINVAL);
                num_elems++;
+       }
 
        elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
        if (!elems)
index 8bf00caf5d29707d714e79e51c354d26e80e8e3e..0cf1ce7b6934238626a9f3173e74af89ee0822cb 100644 (file)
@@ -657,7 +657,7 @@ static int cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies,
 
        ret = cfg80211_calc_short_ssid(ies, &ssid_elem, &s_ssid_tmp);
        if (ret)
-               return ret;
+               return 0;
 
        for_each_element_id(elem, WLAN_EID_REDUCED_NEIGHBOR_REPORT,
                            ies->data, ies->len) {
index 31dca4ecb2c53255063301de141ac1b0189d0244..10ea85c031475e574ed3c4729d6861991a5f6a5a 100644 (file)
@@ -505,7 +505,7 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs,
 
        skb->dev = dev;
        skb->priority = xs->sk.sk_priority;
-       skb->mark = xs->sk.sk_mark;
+       skb->mark = READ_ONCE(xs->sk.sk_mark);
        skb_shinfo(skb)->destructor_arg = (void *)(long)desc->addr;
        skb->destructor = xsk_destruct_skb;
 
@@ -994,6 +994,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
                                err = xp_alloc_tx_descs(xs->pool, xs);
                                if (err) {
                                        xp_put_pool(xs->pool);
+                                       xs->pool = NULL;
                                        sockfd_put(sock);
                                        goto out_unlock;
                                }
index 8cbf45a8bcdc24767c2b31584472f769827fd30b..655fe4ff862122738eb4ab8089ed3a1e45f4cdf1 100644 (file)
@@ -108,7 +108,7 @@ static const struct nla_policy compat_policy[XFRMA_MAX+1] = {
        [XFRMA_ALG_COMP]        = { .len = sizeof(struct xfrm_algo) },
        [XFRMA_ENCAP]           = { .len = sizeof(struct xfrm_encap_tmpl) },
        [XFRMA_TMPL]            = { .len = sizeof(struct xfrm_user_tmpl) },
-       [XFRMA_SEC_CTX]         = { .len = sizeof(struct xfrm_sec_ctx) },
+       [XFRMA_SEC_CTX]         = { .len = sizeof(struct xfrm_user_sec_ctx) },
        [XFRMA_LTIME_VAL]       = { .len = sizeof(struct xfrm_lifetime_cur) },
        [XFRMA_REPLAY_VAL]      = { .len = sizeof(struct xfrm_replay_state) },
        [XFRMA_REPLAY_THRESH]   = { .type = NLA_U32 },
index 815b380804011021d1783094cc90ecc6f3ed6aa4..d5ee96789d4bf3ba3ec2869edeeea5d91a92d677 100644 (file)
@@ -180,6 +180,8 @@ static int xfrm4_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
        int optlen = 0;
        int err = -EINVAL;
 
+       skb->protocol = htons(ETH_P_IP);
+
        if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) {
                struct ip_beet_phdr *ph;
                int phlen;
@@ -232,6 +234,8 @@ static int xfrm4_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err = -EINVAL;
 
+       skb->protocol = htons(ETH_P_IP);
+
        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
                goto out;
 
@@ -267,6 +271,8 @@ static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err = -EINVAL;
 
+       skb->protocol = htons(ETH_P_IPV6);
+
        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
                goto out;
 
@@ -296,6 +302,8 @@ static int xfrm6_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
        int size = sizeof(struct ipv6hdr);
        int err;
 
+       skb->protocol = htons(ETH_P_IPV6);
+
        err = skb_cow_head(skb, size + skb->mac_len);
        if (err)
                goto out;
@@ -346,6 +354,7 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x,
                        return xfrm6_remove_tunnel_encap(x, skb);
                break;
                }
+               return -EINVAL;
        }
 
        WARN_ON_ONCE(1);
@@ -366,19 +375,6 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
                return -EAFNOSUPPORT;
        }
 
-       switch (XFRM_MODE_SKB_CB(skb)->protocol) {
-       case IPPROTO_IPIP:
-       case IPPROTO_BEETPH:
-               skb->protocol = htons(ETH_P_IP);
-               break;
-       case IPPROTO_IPV6:
-               skb->protocol = htons(ETH_P_IPV6);
-               break;
-       default:
-               WARN_ON_ONCE(1);
-               break;
-       }
-
        return xfrm_inner_mode_encap_remove(x, skb);
 }
 
index a3319965470a7b4ae0c26f34403ef835abb1fb37..b864740846902db7f0ab60c6d72465a51b96b1d7 100644 (file)
@@ -537,8 +537,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
 
        switch (skb->protocol) {
        case htons(ETH_P_IPV6):
-               xfrm_decode_session(skb, &fl, AF_INET6);
                memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+               xfrm_decode_session(skb, &fl, AF_INET6);
                if (!dst) {
                        fl.u.ip6.flowi6_oif = dev->ifindex;
                        fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
@@ -552,8 +552,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
                }
                break;
        case htons(ETH_P_IP):
-               xfrm_decode_session(skb, &fl, AF_INET);
                memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+               xfrm_decode_session(skb, &fl, AF_INET);
                if (!dst) {
                        struct rtable *rt;
 
index e7617c9959c311f14e04bfddaa00019df91a812a..d6b405782b6361c4da2e06fae50befbd699aed15 100644 (file)
@@ -2250,7 +2250,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
 
                match = xfrm_selector_match(&pol->selector, fl, family);
                if (match) {
-                       if ((sk->sk_mark & pol->mark.m) != pol->mark.v ||
+                       if ((READ_ONCE(sk->sk_mark) & pol->mark.m) != pol->mark.v ||
                            pol->if_id != if_id) {
                                pol = NULL;
                                goto out;
index 49e63eea841dd773c6d1f5d73cbbacb5fa7e353e..bda5327bf34dfff2d41aafbe57827b6625b73c96 100644 (file)
@@ -1324,12 +1324,8 @@ found:
                        struct xfrm_dev_offload *xso = &x->xso;
 
                        if (xso->type == XFRM_DEV_OFFLOAD_PACKET) {
-                               xso->dev->xfrmdev_ops->xdo_dev_state_delete(x);
-                               xso->dir = 0;
-                               netdev_put(xso->dev, &xso->dev_tracker);
-                               xso->dev = NULL;
-                               xso->real_dev = NULL;
-                               xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
+                               xfrm_dev_state_delete(x);
+                               xfrm_dev_state_free(x);
                        }
 #endif
                        x->km.state = XFRM_STATE_DEAD;
index c34a2a06ca9407230ab66426bf14e39fd04637f4..ad01997c3aa9dd851a3fa4ad6dd6c877eaaddd36 100644 (file)
@@ -628,7 +628,7 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
        struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
        struct nlattr *mt = attrs[XFRMA_MTIMER_THRESH];
 
-       if (re) {
+       if (re && x->replay_esn && x->preplay_esn) {
                struct xfrm_replay_state_esn *replay_esn;
                replay_esn = nla_data(re);
                memcpy(x->replay_esn, replay_esn,
@@ -1267,6 +1267,15 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
                                         sizeof(*filter), GFP_KERNEL);
                        if (filter == NULL)
                                return -ENOMEM;
+
+                       /* see addr_match(), (prefix length >> 5) << 2
+                        * will be used to compare xfrm_address_t
+                        */
+                       if (filter->splen > (sizeof(xfrm_address_t) << 3) ||
+                           filter->dplen > (sizeof(xfrm_address_t) << 3)) {
+                               kfree(filter);
+                               return -EINVAL;
+                       }
                }
 
                if (attrs[XFRMA_PROTO])
@@ -2336,6 +2345,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                                            NETLINK_CB(skb).portid);
                }
        } else {
+               xfrm_dev_policy_delete(xp);
                xfrm_audit_policy_delete(xp, err ? 0 : 1, true);
 
                if (err != 0)
@@ -3015,7 +3025,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
        [XFRMA_ALG_COMP]        = { .len = sizeof(struct xfrm_algo) },
        [XFRMA_ENCAP]           = { .len = sizeof(struct xfrm_encap_tmpl) },
        [XFRMA_TMPL]            = { .len = sizeof(struct xfrm_user_tmpl) },
-       [XFRMA_SEC_CTX]         = { .len = sizeof(struct xfrm_sec_ctx) },
+       [XFRMA_SEC_CTX]         = { .len = sizeof(struct xfrm_user_sec_ctx) },
        [XFRMA_LTIME_VAL]       = { .len = sizeof(struct xfrm_lifetime_cur) },
        [XFRMA_REPLAY_VAL]      = { .len = sizeof(struct xfrm_replay_state) },
        [XFRMA_REPLAY_THRESH]   = { .type = NLA_U32 },
@@ -3035,6 +3045,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
        [XFRMA_SET_MARK]        = { .type = NLA_U32 },
        [XFRMA_SET_MARK_MASK]   = { .type = NLA_U32 },
        [XFRMA_IF_ID]           = { .type = NLA_U32 },
+       [XFRMA_MTIMER_THRESH]   = { .type = NLA_U32 },
 };
 EXPORT_SYMBOL_GPL(xfrma_policy);
 
index 7c9d9f11aec50572ba63ac1d77e86c37f06e1344..4124bfa01798d6244f9fcf854452cde378e13c4d 100644 (file)
@@ -257,7 +257,7 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \
        -fno-partial-inlining -fplugin-arg-arm_ssp_per_task_plugin-% \
        -fno-reorder-blocks -fno-allow-store-data-races -fasan-shadow-offset=% \
        -fzero-call-used-regs=% -fno-stack-clash-protection \
-       -fno-inline-functions-called-once \
+       -fno-inline-functions-called-once -fsanitize=bounds-strict \
        --param=% --param asan-%
 
 # Derived from `scripts/Makefile.clang`.
index 3e601ce2548d4ff483bd291e5d114a2ab74ceee3..058954961bfc07437e0dcf9cc4bb3d51674a43da 100644 (file)
@@ -13,5 +13,6 @@
 #include <linux/sched.h>
 
 /* `bindgen` gets confused at certain things. */
+const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
 const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
 const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO;
index 397a3dd57a9b132f9982e213868bc558ed843f27..9363b527be664515313c60bbe21181877e766fdb 100644 (file)
@@ -9,6 +9,36 @@ use crate::bindings;
 
 struct KernelAllocator;
 
+/// Calls `krealloc` with a proper size to alloc a new object aligned to `new_layout`'s alignment.
+///
+/// # Safety
+///
+/// - `ptr` can be either null or a pointer which has been allocated by this allocator.
+/// - `new_layout` must have a non-zero size.
+unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: bindings::gfp_t) -> *mut u8 {
+    // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first.
+    let layout = new_layout.pad_to_align();
+
+    let mut size = layout.size();
+
+    if layout.align() > bindings::BINDINGS_ARCH_SLAB_MINALIGN {
+        // The alignment requirement exceeds the slab guarantee, thus try to enlarge the size
+        // to use the "power-of-two" size/alignment guarantee (see comments in `kmalloc()` for
+        // more information).
+        //
+        // Note that `layout.size()` (after padding) is guaranteed to be a multiple of
+        // `layout.align()`, so `next_power_of_two` gives enough alignment guarantee.
+        size = size.next_power_of_two();
+    }
+
+    // SAFETY:
+    // - `ptr` is either null or a pointer returned from a previous `k{re}alloc()` by the
+    //   function safety requirement.
+    // - `size` is greater than 0 since it's either a `layout.size()` (which cannot be zero
+    //    according to the function safety requirement) or a result from `next_power_of_two()`.
+    unsafe { bindings::krealloc(ptr as *const core::ffi::c_void, size, flags) as *mut u8 }
+}
+
 unsafe impl GlobalAlloc for KernelAllocator {
     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
         // `krealloc()` is used instead of `kmalloc()` because the latter is
@@ -30,10 +60,20 @@ static ALLOCATOR: KernelAllocator = KernelAllocator;
 // to extract the object file that has them from the archive. For the moment,
 // let's generate them ourselves instead.
 //
+// Note: Although these are *safe* functions, they are called by the compiler
+// with parameters that obey the same `GlobalAlloc` function safety
+// requirements: size and align should form a valid layout, and size is
+// greater than 0.
+//
 // Note that `#[no_mangle]` implies exported too, nowadays.
 #[no_mangle]
-fn __rust_alloc(size: usize, _align: usize) -> *mut u8 {
-    unsafe { bindings::krealloc(core::ptr::null(), size, bindings::GFP_KERNEL) as *mut u8 }
+fn __rust_alloc(size: usize, align: usize) -> *mut u8 {
+    // SAFETY: See assumption above.
+    let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
+
+    // SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater
+    // than 0.
+    unsafe { krealloc_aligned(ptr::null_mut(), layout, bindings::GFP_KERNEL) }
 }
 
 #[no_mangle]
@@ -42,23 +82,27 @@ fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) {
 }
 
 #[no_mangle]
-fn __rust_realloc(ptr: *mut u8, _old_size: usize, _align: usize, new_size: usize) -> *mut u8 {
-    unsafe {
-        bindings::krealloc(
-            ptr as *const core::ffi::c_void,
-            new_size,
-            bindings::GFP_KERNEL,
-        ) as *mut u8
-    }
+fn __rust_realloc(ptr: *mut u8, _old_size: usize, align: usize, new_size: usize) -> *mut u8 {
+    // SAFETY: See assumption above.
+    let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, align) };
+
+    // SAFETY: Per assumption above, `ptr` is allocated by `__rust_*` before, and the size of
+    // `new_layout` is greater than 0.
+    unsafe { krealloc_aligned(ptr, new_layout, bindings::GFP_KERNEL) }
 }
 
 #[no_mangle]
-fn __rust_alloc_zeroed(size: usize, _align: usize) -> *mut u8 {
+fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
+    // SAFETY: See assumption above.
+    let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
+
+    // SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater
+    // than 0.
     unsafe {
-        bindings::krealloc(
-            core::ptr::null(),
-            size,
+        krealloc_aligned(
+            ptr::null_mut(),
+            layout,
             bindings::GFP_KERNEL | bindings::__GFP_ZERO,
-        ) as *mut u8
+        )
     }
 }
index a89843cacaad075eafada7490bc87c5311f85d83..172f563976a9c090ad8364c5786ddecb5f70bfdb 100644 (file)
@@ -243,8 +243,7 @@ impl<T: 'static> ForeignOwnable for Arc<T> {
         let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap();
 
         // SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive
-        // for the lifetime of the returned value. Additionally, the safety requirements of
-        // `ForeignOwnable::borrow_mut` ensure that no new mutable references are created.
+        // for the lifetime of the returned value.
         unsafe { ArcBorrow::new(inner) }
     }
 
index 1e5380b16ed55300d0d9d3867fc5eb28bec40d30..d479f8da8f3812ce450f17affdf88bc24adb4864 100644 (file)
@@ -35,34 +35,16 @@ pub trait ForeignOwnable: Sized {
     ///
     /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
     /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
-    /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow_mut`]
-    /// for this object must have been dropped.
     unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>;
 
-    /// Mutably borrows a foreign-owned object.
-    ///
-    /// # Safety
-    ///
-    /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
-    /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
-    /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and
-    /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped.
-    unsafe fn borrow_mut(ptr: *const core::ffi::c_void) -> ScopeGuard<Self, fn(Self)> {
-        // SAFETY: The safety requirements ensure that `ptr` came from a previous call to
-        // `into_foreign`.
-        ScopeGuard::new_with_data(unsafe { Self::from_foreign(ptr) }, |d| {
-            d.into_foreign();
-        })
-    }
-
     /// Converts a foreign-owned object back to a Rust-owned one.
     ///
     /// # Safety
     ///
     /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
     /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
-    /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and
-    /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped.
+    /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] for
+    /// this object must have been dropped.
     unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self;
 }
 
index 34d5e7fb5768a242f417c19345146cc1b6cfe638..ee06044fcd4f35cdb40be79c16d9c5b5995841a5 100644 (file)
@@ -74,6 +74,7 @@ pub(crate) fn vtable(_attr: TokenStream, ts: TokenStream) -> TokenStream {
                 const {gen_const_name}: bool = false;",
             )
             .unwrap();
+            consts.insert(gen_const_name);
         }
     } else {
         const_items = "const USE_VTABLE_ATTR: () = ();".to_owned();
index 16c87938b3165c2be64eb5886b9ed4c4e7e15c01..653b92f6d4c8f49f9824f8ddd943c36bf53ede23 100644 (file)
@@ -129,6 +129,7 @@ static struct sym_entry *read_symbol(FILE *in, char **buf, size_t *buf_len)
        ssize_t readlen;
        struct sym_entry *sym;
 
+       errno = 0;
        readlen = getline(buf, buf_len, in);
        if (readlen < 0) {
                if (errno) {
index b72b82bb20c65e3b70e0fc3d0f6afe5c24e62376..b348e1679d5df6a430aff60853632472df8cbdfb 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/sysctl.h>
 #include "internal.h"
 
-struct ctl_table key_sysctls[] = {
+static struct ctl_table key_sysctls[] = {
        {
                .procname = "maxkeys",
                .data = &key_quota_maxkeys,
index 31b08b34c72249b635a87a1424c405dce50b31fb..dc904865af58e1bd0f096883f19a519c11e16653 100644 (file)
@@ -2005,6 +2005,7 @@ static int filename_trans_read_helper(struct policydb *p, void *fp)
                if (!datum)
                        goto out;
 
+               datum->next = NULL;
                *dst = datum;
 
                /* ebitmap_read() will at least init the bitmap */
@@ -2017,7 +2018,6 @@ static int filename_trans_read_helper(struct policydb *p, void *fp)
                        goto out;
 
                datum->otype = le32_to_cpu(buf[0]);
-               datum->next = NULL;
 
                dst = &datum->next;
        }
index b288874e401e5ce58358c7eccd9e7b26f7c8219e..36b411d1a9609a9b2e9f5cd8097c17b47dae04a9 100644 (file)
@@ -550,6 +550,10 @@ const struct snd_pci_quirk cs8409_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0C50, "Dolphin", CS8409_DOLPHIN),
        SND_PCI_QUIRK(0x1028, 0x0C51, "Dolphin", CS8409_DOLPHIN),
        SND_PCI_QUIRK(0x1028, 0x0C52, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0C73, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0C75, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0C7D, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0C7F, "Dolphin", CS8409_DOLPHIN),
        {} /* terminator */
 };
 
index 44fccfb93cff467caf540d201f1e0cfb58bed453..dc7b7a407638a76c959e9a3470fbf2af4b888630 100644 (file)
@@ -9422,11 +9422,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0cbd, "Dell Oasis 13 CS MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1028, 0x0cbe, "Dell Oasis 13 2-IN-1 MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1028, 0x0cbf, "Dell Oasis 13 Low Weight MTU-L", ALC245_FIXUP_CS35L41_SPI_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc1, "Dell Oasis 14 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc2, "Dell Oasis 14 2-in-1 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc3, "Dell Oasis 14 Low Weight MTL-U", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc4, "Dell Oasis 16 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc5, "Dell Oasis MLK 14 RPL-P", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc1, "Dell Oasis 14 MTL-H/U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc2, "Dell Oasis 14 2-in-1 MTL-H/U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc3, "Dell Oasis 14 Low Weight MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc4, "Dell Oasis 16 MTL-H/U", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -9617,7 +9616,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8b96, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b97, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
-       SND_PCI_QUIRK(0x103c, 0x8c26, "HP HP EliteBook 800G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c46, "HP EliteBook 830 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c47, "HP EliteBook 840 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c48, "HP EliteBook 860 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c49, "HP Elite x360 830 2-in-1 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c70, "HP EliteBook 835 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c71, "HP EliteBook 845 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c72, "HP EliteBook 865 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -10638,6 +10643,7 @@ static int patch_alc269(struct hda_codec *codec)
        spec = codec->spec;
        spec->gen.shared_mic_vref_pin = 0x18;
        codec->power_save_node = 0;
+       spec->en_3kpull_low = true;
 
 #ifdef CONFIG_PM
        codec->patch_ops.suspend = alc269_suspend;
@@ -10720,14 +10726,16 @@ static int patch_alc269(struct hda_codec *codec)
                spec->shutup = alc256_shutup;
                spec->init_hook = alc256_init;
                spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
-               if (codec->bus->pci->vendor == PCI_VENDOR_ID_AMD)
-                       spec->en_3kpull_low = true;
+               if (codec->core.vendor_id == 0x10ec0236 &&
+                   codec->bus->pci->vendor != PCI_VENDOR_ID_AMD)
+                       spec->en_3kpull_low = false;
                break;
        case 0x10ec0257:
                spec->codec_variant = ALC269_TYPE_ALC257;
                spec->shutup = alc256_shutup;
                spec->init_hook = alc256_init;
                spec->gen.mixer_nid = 0;
+               spec->en_3kpull_low = false;
                break;
        case 0x10ec0215:
        case 0x10ec0245:
index b5c69bba0e4888fa21e55e0430893196cb5a3a51..2dfaf4fcfbd37ac3ad0faf96ea7eca48fbdbd2b8 100644 (file)
@@ -185,10 +185,10 @@ static int max98363_io_init(struct sdw_slave *slave)
        pm_runtime_get_noresume(dev);
 
        ret = regmap_read(max98363->regmap, MAX98363_R21FF_REV_ID, &reg);
-       if (!ret) {
+       if (!ret)
                dev_info(dev, "Revision ID: %X\n", reg);
-               return ret;
-       }
+       else
+               goto out;
 
        if (max98363->first_hw_init) {
                regcache_cache_bypass(max98363->regmap, false);
@@ -198,10 +198,11 @@ static int max98363_io_init(struct sdw_slave *slave)
        max98363->first_hw_init = true;
        max98363->hw_init = true;
 
+out:
        pm_runtime_mark_last_busy(dev);
        pm_runtime_put_autosuspend(dev);
 
-       return 0;
+       return ret;
 }
 
 #define MAX98363_RATES SNDRV_PCM_RATE_8000_192000
index f43520ca318740bd9577ab4823505bb6d8e3b0c2..e566c8ddd3e97b94129a4ac535344a49b7c75e19 100644 (file)
@@ -52,6 +52,7 @@ static bool rt1308_volatile_register(struct device *dev, unsigned int reg)
        case 0x300a:
        case 0xc000:
        case 0xc710:
+       case 0xcf01:
        case 0xc860 ... 0xc863:
        case 0xc870 ... 0xc873:
                return true;
@@ -213,7 +214,7 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave)
 {
        struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev);
        int ret = 0;
-       unsigned int tmp;
+       unsigned int tmp, hibernation_flag;
 
        if (rt1308->hw_init)
                return 0;
@@ -242,6 +243,10 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave)
 
        pm_runtime_get_noresume(&slave->dev);
 
+       regmap_read(rt1308->regmap, 0xcf01, &hibernation_flag);
+       if ((hibernation_flag != 0x00) && rt1308->first_hw_init)
+               goto _preset_ready_;
+
        /* sw reset */
        regmap_write(rt1308->regmap, RT1308_SDW_RESET, 0);
 
@@ -282,6 +287,12 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave)
        regmap_write(rt1308->regmap, 0xc100, 0xd7);
        regmap_write(rt1308->regmap, 0xc101, 0xd7);
 
+       /* apply BQ params */
+       rt1308_apply_bq_params(rt1308);
+
+       regmap_write(rt1308->regmap, 0xcf01, 0x01);
+
+_preset_ready_:
        if (rt1308->first_hw_init) {
                regcache_cache_bypass(rt1308->regmap, false);
                regcache_mark_dirty(rt1308->regmap);
index 83c367af91dad4697dbc0ff3499a26dd739f8220..525713c33d71622953f66233cb6af533085bac72 100644 (file)
@@ -4472,6 +4472,8 @@ static void rt5665_remove(struct snd_soc_component *component)
        struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component);
 
        regmap_write(rt5665->regmap, RT5665_RESET, 0);
+
+       regulator_bulk_disable(ARRAY_SIZE(rt5665->supplies), rt5665->supplies);
 }
 
 #ifdef CONFIG_PM
index 3f08082a55bec27e498726cdcd6bcd3c2783a152..9d01225dedd9a1470c45e45df999861c99630677 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 // Copyright 2018 NXP
 
 #include <linux/bitfield.h>
@@ -1254,4 +1254,4 @@ module_platform_driver(fsl_micfil_driver);
 
 MODULE_AUTHOR("Cosmin-Gabriel Samoila <cosmin.samoila@nxp.com>");
 MODULE_DESCRIPTION("NXP PDM Microphone Interface (MICFIL) driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("Dual BSD/GPL");
index 9237a1c4cb8f7781671acb5c4f9e2e42dd732ab4..fee9fe3d91199146b326b09aa022653fd35f44c3 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
  * PDM Microphone Interface for the NXP i.MX SoC
  * Copyright 2018 NXP
index dbee8c98ff0122b1a5cfec54e6cf4a4683766cc7..0201029899cad62991da5090e501f14eebf9cb48 100644 (file)
@@ -476,7 +476,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"),
                },
-               .driver_data = (void *)(RT711_JD2_100K),
+               .driver_data = (void *)(RT711_JD2),
        },
        {}
 };
index c4a16e4c9f69c047605d37d10802ab23604e9183..ad130d913415e090be14d97e5c998e2151672bb7 100644 (file)
@@ -99,9 +99,9 @@ static int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd)
        jack = &ctx->sdw_headset;
 
        snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
-       snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
-       snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
-       snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
 
        ret = snd_soc_component_set_jack(component, jack, NULL);
 
index 9883dc777f630ce2adbf1614480b4e60bc3f4c58..63333a2b0a9c363d6882d3fe50ecff78da390316 100644 (file)
@@ -30,27 +30,32 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map,
                                        struct axg_tdm_stream *ts,
                                        unsigned int offset)
 {
-       unsigned int val, ch = ts->channels;
-       unsigned long mask;
-       int i, j;
+       unsigned int ch = ts->channels;
+       u32 val[AXG_TDM_NUM_LANES];
+       int i, j, k;
+
+       /*
+        * We need to mimick the slot distribution used by the HW to keep the
+        * channel placement consistent regardless of the number of channel
+        * in the stream. This is why the odd algorithm below is used.
+        */
+       memset(val, 0, sizeof(*val) * AXG_TDM_NUM_LANES);
 
        /*
         * Distribute the channels of the stream over the available slots
-        * of each TDM lane
+        * of each TDM lane. We need to go over the 32 slots ...
         */
-       for (i = 0; i < AXG_TDM_NUM_LANES; i++) {
-               val = 0;
-               mask = ts->mask[i];
-
-               for (j = find_first_bit(&mask, 32);
-                    (j < 32) && ch;
-                    j = find_next_bit(&mask, 32, j + 1)) {
-                       val |= 1 << j;
-                       ch -= 1;
+       for (i = 0; (i < 32) && ch; i += 2) {
+               /* ... of all the lanes ... */
+               for (j = 0; j < AXG_TDM_NUM_LANES; j++) {
+                       /* ... then distribute the channels in pairs */
+                       for (k = 0; k < 2; k++) {
+                               if ((BIT(i + k) & ts->mask[j]) && ch) {
+                                       val[j] |= BIT(i + k);
+                                       ch -= 1;
+                               }
+                       }
                }
-
-               regmap_write(map, offset, val);
-               offset += regmap_get_reg_stride(map);
        }
 
        /*
@@ -63,6 +68,11 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map,
                return -EINVAL;
        }
 
+       for (i = 0; i < AXG_TDM_NUM_LANES; i++) {
+               regmap_write(map, offset, val[i]);
+               offset += regmap_get_reg_stride(map);
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks);
index 8896227e4fb76000dec354b6ddf7af6431684900..3aa6b988cb4b492faf801434302cc28f844adf6c 100644 (file)
@@ -38,6 +38,7 @@ static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd,
        switch (ret) {
        case -EPROBE_DEFER:
        case -ENOTSUPP:
+       case -EINVAL:
                break;
        default:
                dev_err(rtd->dev,
@@ -2466,8 +2467,11 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
 
        /* there is no point preparing this FE if there are no BEs */
        if (list_empty(&fe->dpcm[stream].be_clients)) {
-               dev_err(fe->dev, "ASoC: no backend DAIs enabled for %s\n",
-                               fe->dai_link->name);
+               /* dev_err_once() for visibility, dev_dbg() for debugging UCM profiles */
+               dev_err_once(fe->dev, "ASoC: no backend DAIs enabled for %s, possibly missing ALSA mixer-based routing or UCM profile\n",
+                            fe->dai_link->name);
+               dev_dbg(fe->dev, "ASoC: no backend DAIs enabled for %s\n",
+                       fe->dai_link->name);
                ret = -EINVAL;
                goto out;
        }
index f3513796c189c6972ea5d614ef70fdb38901a3d9..f33051eac1c096e1c1494dc84ce610195dd81b85 100644 (file)
@@ -372,6 +372,7 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = {
 static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
                                 struct snd_pcm_substream *substream, int cmd)
 {
+       struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
        struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
 
        switch (cmd) {
@@ -379,9 +380,17 @@ static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
        case SNDRV_PCM_TRIGGER_STOP:
        {
                struct snd_sof_dai_config_data data = { 0 };
+               int ret;
 
                data.dai_data = DMA_CHAN_INVALID;
-               return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data);
+               ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data);
+               if (ret < 0)
+                       return ret;
+
+               if (cmd == SNDRV_PCM_TRIGGER_STOP)
+                       return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
+
+               break;
        }
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
index 3297dea493aa60594578a411ebb823facc37a092..863865f3d77ebb88d9639ec137c248b6282eecb0 100644 (file)
@@ -107,9 +107,8 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai
        return sdai->platform_private;
 }
 
-static int hda_link_dma_cleanup(struct snd_pcm_substream *substream,
-                               struct hdac_ext_stream *hext_stream,
-                               struct snd_soc_dai *cpu_dai)
+int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream,
+                        struct snd_soc_dai *cpu_dai)
 {
        const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
        struct sof_intel_hda_stream *hda_stream;
index 3f7c6fb05e5d7535df0ba5eb6d698229338201ef..5b9e4ebcc18b24683ce7913ea57b3a98b564298d 100644 (file)
@@ -963,5 +963,7 @@ const struct hda_dai_widget_dma_ops *
 hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget);
 int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
                   struct snd_sof_dai_config_data *data);
+int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream,
+                        struct snd_soc_dai *cpu_dai);
 
 #endif
index 2c5aac31e8b0712ec05ef46724d14e7414fede02..580960ff273d1c3ea940e4db474cd17291806624 100644 (file)
@@ -1001,7 +1001,7 @@ void sof_ipc3_do_rx_work(struct snd_sof_dev *sdev, struct sof_ipc_cmd_hdr *hdr,
 
        ipc3_log_header(sdev->dev, "ipc rx", hdr->cmd);
 
-       if (hdr->size < sizeof(hdr) || hdr->size > SOF_IPC_MSG_MAX_SIZE) {
+       if (hdr->size < sizeof(*hdr) || hdr->size > SOF_IPC_MSG_MAX_SIZE) {
                dev_err(sdev->dev, "The received message size is invalid: %u\n",
                        hdr->size);
                return;
index a4e1a70b607d9bb6d6b9661a5da53aa015fbcb11..11361e1cd6881b9ddde1b87a910c6449b62228c6 100644 (file)
@@ -1731,6 +1731,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
 
        *ipc_config_size = ipc_size;
 
+       /* update pipeline memory usage */
+       sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config);
+
        /* copy IPC data */
        memcpy(*ipc_config_data, (void *)copier_data, sizeof(*copier_data));
        if (gtw_cfg_config_length)
@@ -1743,9 +1746,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
                       gtw_cfg_config_length,
                       &ipc4_copier->dma_config_tlv, dma_config_tlv_size);
 
-       /* update pipeline memory usage */
-       sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config);
-
        return 0;
 }
 
index efb4a3311cc5929cd289440f5ae042a4e20d8560..5d72dc8441cbb49c6258e28fb3e642d844c81b41 100644 (file)
@@ -4507,6 +4507,35 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       /* Advanced modes of the Mythware XA001AU.
+        * For the standard mode, Mythware XA001AU has ID ffad:a001
+        */
+       USB_DEVICE_VENDOR_SPEC(0xffad, 0xa001),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "Mythware",
+               .product_name = "XA001AU",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE,
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE,
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE,
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 #undef USB_DEVICE_VENDOR_SPEC
 #undef USB_AUDIO_DEVICE
diff --git a/tools/arch/arm64/include/uapi/asm/bitsperlong.h b/tools/arch/arm64/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..485d60b
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_BITSPERLONG_H
+#define __ASM_BITSPERLONG_H
+
+#define __BITS_PER_LONG 64
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_BITSPERLONG_H */
diff --git a/tools/arch/riscv/include/uapi/asm/bitsperlong.h b/tools/arch/riscv/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..0b9b58b
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2015 Regents of the University of California
+ */
+
+#ifndef _UAPI_ASM_RISCV_BITSPERLONG_H
+#define _UAPI_ASM_RISCV_BITSPERLONG_H
+
+#define __BITS_PER_LONG (__SIZEOF_POINTER__ * 8)
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* _UAPI_ASM_RISCV_BITSPERLONG_H */
index cb8ca46213bed0a837d9e134877f623c4e0e0525..1f6d904c6481dd4414d67be8e0acec46ed337c57 100644 (file)
@@ -14,7 +14,7 @@
  * Defines x86 CPU feature bits
  */
 #define NCAPINTS                       21         /* N 32-bit words worth of info */
-#define NBUGINTS                       1          /* N 32-bit bug flags */
+#define NBUGINTS                       2          /* N 32-bit bug flags */
 
 /*
  * Note: If the comment begins with a quoted string, that string is used
index 3aedae61af4fcb945383ea486066d43982f28462..a00a53e15ab73883e2d289aabe06db84b3208e8a 100644 (file)
 #define MSR_AMD64_DE_CFG               0xc0011029
 #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT   1
 #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE      BIT_ULL(MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT)
+#define MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT 9
 
 #define MSR_AMD64_BU_CFG2              0xc001102a
 #define MSR_AMD64_IBSFETCHCTL          0xc0011030
index a0f4cab71fe5ff2341e581d6d942225ce2d240f2..b2c2946f44c9f3320188692353a160853cc4f05d 100644 (file)
@@ -40,7 +40,8 @@ $(OUTPUT)counter_example: $(COUNTER_EXAMPLE)
 clean:
        rm -f $(ALL_PROGRAMS)
        rm -rf $(OUTPUT)include/linux/counter.h
-       rmdir -p $(OUTPUT)include/linux
+       rm -df $(OUTPUT)include/linux
+       rm -df $(OUTPUT)include
        find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
 
 install: $(ALL_PROGRAMS)
index e7212903dd1d92b80c3a82b9ab0bcbd1f138f882..4467979d8f69976ac905efaa04d1a447ce9ed6c4 100755 (executable)
@@ -164,7 +164,7 @@ def recursive_file_lookup(path, file_map):
 def get_all_devices_test_status(file_map):
 
         for device in file_map:
-                if (get_test_state(locate_state(device, file_map)) is 1):
+                if (get_test_state(locate_state(device, file_map)) == 1):
                         print("Testing = ON for: {}"
                               .format(device.split("/")[5]))
                 else:
@@ -203,7 +203,7 @@ def write_test_files(path, value):
 def set_test_state(state_path, state_value, quiet):
 
         write_test_files(state_path, state_value)
-        if (get_test_state(state_path) is 1):
+        if (get_test_state(state_path) == 1):
                 if (not quiet):
                         print("Testing = ON for device: {}"
                               .format(state_path.split("/")[5]))
index 2e1caabecb1858679b2149d396bf7f078772c48e..c0f25d00181ec27e06eb8e6d8fc094f6dea92fd5 100644 (file)
@@ -826,3 +826,9 @@ bool arch_is_rethunk(struct symbol *sym)
 {
        return !strcmp(sym->name, "__x86_return_thunk");
 }
+
+bool arch_is_embedded_insn(struct symbol *sym)
+{
+       return !strcmp(sym->name, "retbleed_return_thunk") ||
+              !strcmp(sym->name, "srso_safe_ret");
+}
index 8936a05f0e5acbb151e7547b01a23268d711dfcb..1384090530dbe3e7e0c018c833aeacdf2f95b720 100644 (file)
@@ -389,7 +389,7 @@ static int decode_instructions(struct objtool_file *file)
                if (!strcmp(sec->name, ".noinstr.text") ||
                    !strcmp(sec->name, ".entry.text") ||
                    !strcmp(sec->name, ".cpuidle.text") ||
-                   !strncmp(sec->name, ".text.__x86.", 12))
+                   !strncmp(sec->name, ".text..__x86.", 13))
                        sec->noinstr = true;
 
                /*
@@ -455,7 +455,7 @@ static int decode_instructions(struct objtool_file *file)
                                return -1;
                        }
 
-                       if (func->return_thunk || func->alias != func)
+                       if (func->embedded_insn || func->alias != func)
                                continue;
 
                        if (!find_insn(file, sec, func->offset)) {
@@ -1288,16 +1288,33 @@ static int add_ignore_alternatives(struct objtool_file *file)
        return 0;
 }
 
+/*
+ * Symbols that replace INSN_CALL_DYNAMIC, every (tail) call to such a symbol
+ * will be added to the .retpoline_sites section.
+ */
 __weak bool arch_is_retpoline(struct symbol *sym)
 {
        return false;
 }
 
+/*
+ * Symbols that replace INSN_RETURN, every (tail) call to such a symbol
+ * will be added to the .return_sites section.
+ */
 __weak bool arch_is_rethunk(struct symbol *sym)
 {
        return false;
 }
 
+/*
+ * Symbols that are embedded inside other instructions, because sometimes crazy
+ * code exists. These are mostly ignored for validation purposes.
+ */
+__weak bool arch_is_embedded_insn(struct symbol *sym)
+{
+       return false;
+}
+
 static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn)
 {
        struct reloc *reloc;
@@ -1576,14 +1593,14 @@ static int add_jump_destinations(struct objtool_file *file)
                        struct symbol *sym = find_symbol_by_offset(dest_sec, dest_off);
 
                        /*
-                        * This is a special case for zen_untrain_ret().
+                        * This is a special case for retbleed_untrain_ret().
                         * It jumps to __x86_return_thunk(), but objtool
                         * can't find the thunk's starting RET
                         * instruction, because the RET is also in the
                         * middle of another instruction.  Objtool only
                         * knows about the outer instruction.
                         */
-                       if (sym && sym->return_thunk) {
+                       if (sym && sym->embedded_insn) {
                                add_return_call(file, insn, false);
                                continue;
                        }
@@ -2502,6 +2519,9 @@ static int classify_symbols(struct objtool_file *file)
                if (arch_is_rethunk(func))
                        func->return_thunk = true;
 
+               if (arch_is_embedded_insn(func))
+                       func->embedded_insn = true;
+
                if (arch_ftrace_match(func->name))
                        func->fentry = true;
 
@@ -2630,12 +2650,17 @@ static int decode_sections(struct objtool_file *file)
        return 0;
 }
 
-static bool is_fentry_call(struct instruction *insn)
+static bool is_special_call(struct instruction *insn)
 {
-       if (insn->type == INSN_CALL &&
-           insn_call_dest(insn) &&
-           insn_call_dest(insn)->fentry)
-               return true;
+       if (insn->type == INSN_CALL) {
+               struct symbol *dest = insn_call_dest(insn);
+
+               if (!dest)
+                       return false;
+
+               if (dest->fentry || dest->embedded_insn)
+                       return true;
+       }
 
        return false;
 }
@@ -3636,7 +3661,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
                        if (ret)
                                return ret;
 
-                       if (opts.stackval && func && !is_fentry_call(insn) &&
+                       if (opts.stackval && func && !is_special_call(insn) &&
                            !has_valid_stack_frame(&state)) {
                                WARN_INSN(insn, "call without frame pointer save/setup");
                                return 1;
index 2b6d2ce4f9a5bfd7a9cdb2d343c662996ed10ead..0b303eba660e4625757682544a3b4a555e288511 100644 (file)
@@ -90,6 +90,7 @@ int arch_decode_hint_reg(u8 sp_reg, int *base);
 
 bool arch_is_retpoline(struct symbol *sym);
 bool arch_is_rethunk(struct symbol *sym);
+bool arch_is_embedded_insn(struct symbol *sym);
 
 int arch_rewrite_retpolines(struct objtool_file *file);
 
index c532d70864dc58b3bc2fdc270f4eb1bf10df143c..9f71e988eca45fd6bc81734b9a52d76b895e9517 100644 (file)
@@ -66,6 +66,7 @@ struct symbol {
        u8 fentry            : 1;
        u8 profiling_func    : 1;
        u8 warned            : 1;
+       u8 embedded_insn     : 1;
        struct list_head pv_target;
        struct reloc *relocs;
 };
index 561de0cb6b95880dfb0af23b9c769a27366846e1..512a8f13c4de42aba55eee37a06bd9a3dca332de 100644 (file)
@@ -54,10 +54,11 @@ double perf_pmu__cpu_slots_per_cycle(void)
                perf_pmu__pathname_scnprintf(path, sizeof(path),
                                             pmu->name, "caps/slots");
                /*
-                * The value of slots is not greater than 32 bits, but sysfs__read_int
-                * can't read value with 0x prefix, so use sysfs__read_ull instead.
+                * The value of slots is not greater than 32 bits, but
+                * filename__read_int can't read value with 0x prefix,
+                * so use filename__read_ull instead.
                 */
-               sysfs__read_ull(path, &slots);
+               filename__read_ull(path, &slots);
        }
 
        return slots ? (double)slots : NAN;
index b7223feec770dc33917ebdc0c0cc109d42277b2c..5f3edb3004d84f58ebb5c11c5814f9f3fb836989 100644 (file)
@@ -250,6 +250,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
        if (!chain || chain->nr < 3)
                return skip_slot;
 
+       addr_location__init(&al);
        ip = chain->ips[1];
 
        thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
@@ -259,6 +260,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
 
        if (!dso) {
                pr_debug("%" PRIx64 " dso is NULL\n", ip);
+               addr_location__exit(&al);
                return skip_slot;
        }
 
@@ -279,5 +281,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
                 */
                skip_slot = 3;
        }
+
+       addr_location__exit(&al);
        return skip_slot;
 }
index b2f82847e4c39820713cd79ef17d6fbae88ba1ba..658fb9599d952f5385864c8bf436340dcaa735ab 100644 (file)
@@ -1631,6 +1631,16 @@ static bool test__pmu_cpu_valid(void)
        return !!perf_pmus__find("cpu");
 }
 
+static bool test__pmu_cpu_event_valid(void)
+{
+       struct perf_pmu *pmu = perf_pmus__find("cpu");
+
+       if (!pmu)
+               return false;
+
+       return perf_pmu__has_format(pmu, "event");
+}
+
 static bool test__intel_pt_valid(void)
 {
        return !!perf_pmus__find("intel_pt");
@@ -2179,7 +2189,7 @@ static const struct evlist_test test__events_pmu[] = {
        },
        {
                .name  = "cpu/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp",
-               .valid = test__pmu_cpu_valid,
+               .valid = test__pmu_cpu_event_valid,
                .check = test__checkevent_complex_name,
                /* 3 */
        },
index 00d2e0e2e0c28d65eb6ce8696d63936ef8aa86b2..319f36ebb9a40aebe0626f1dcb94488686f9a296 100755 (executable)
@@ -4,6 +4,12 @@
 
 set -e
 
+# skip if there's no gcc
+if ! [ -x "$(command -v gcc)" ]; then
+        echo "failed: no gcc compiler"
+        exit 2
+fi
+
 temp_dir=$(mktemp -d /tmp/perf-uprobe-different-cu-sh.XXXXXXXXXX)
 
 cleanup()
@@ -11,7 +17,7 @@ cleanup()
        trap - EXIT TERM INT
        if [[ "${temp_dir}" =~ ^/tmp/perf-uprobe-different-cu-sh.*$ ]]; then
                echo "--- Cleaning up ---"
-               perf probe -x ${temp_dir}/testfile -d foo
+               perf probe -x ${temp_dir}/testfile -d foo || true
                rm -f "${temp_dir}/"*
                rmdir "${temp_dir}"
        fi
index 4e62843d51b7dbf9f930594db3699b36c36b9082..f4cb41ee23cdbcfcf6e287025b83fd27ab3a11ee 100644 (file)
@@ -45,7 +45,6 @@
 
 static void __machine__remove_thread(struct machine *machine, struct thread_rb_node *nd,
                                     struct thread *th, bool lock);
-static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip);
 
 static struct dso *machine__kernel_dso(struct machine *machine)
 {
@@ -2385,10 +2384,6 @@ static int add_callchain_ip(struct thread *thread,
        ms.maps = maps__get(al.maps);
        ms.map = map__get(al.map);
        ms.sym = al.sym;
-
-       if (!branch && append_inlines(cursor, &ms, ip) == 0)
-               goto out;
-
        srcline = callchain_srcline(&ms, al.addr);
        err = callchain_cursor_append(cursor, ip, &ms,
                                      branch, flags, nr_loop_iter,
index acde097e327cce8c0f4be708f49195f7a8445052..c9ec0cafb69d060ff5bae344d157e8fb9345f2e8 100644 (file)
@@ -2100,16 +2100,16 @@ __weak int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs)
        return lhs->core.idx - rhs->core.idx;
 }
 
-static int evlist__cmp(void *state, const struct list_head *l, const struct list_head *r)
+static int evlist__cmp(void *_fg_idx, const struct list_head *l, const struct list_head *r)
 {
        const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node);
        const struct evsel *lhs = container_of(lhs_core, struct evsel, core);
        const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node);
        const struct evsel *rhs = container_of(rhs_core, struct evsel, core);
-       int *leader_idx = state;
-       int lhs_leader_idx = *leader_idx, rhs_leader_idx = *leader_idx, ret;
+       int *force_grouped_idx = _fg_idx;
+       int lhs_sort_idx, rhs_sort_idx, ret;
        const char *lhs_pmu_name, *rhs_pmu_name;
-       bool lhs_has_group = false, rhs_has_group = false;
+       bool lhs_has_group, rhs_has_group;
 
        /*
         * First sort by grouping/leader. Read the leader idx only if the evsel
@@ -2121,15 +2121,25 @@ static int evlist__cmp(void *state, const struct list_head *l, const struct list
         */
        if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) {
                lhs_has_group = true;
-               lhs_leader_idx = lhs_core->leader->idx;
+               lhs_sort_idx = lhs_core->leader->idx;
+       } else {
+               lhs_has_group = false;
+               lhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(lhs)
+                       ? *force_grouped_idx
+                       : lhs_core->idx;
        }
        if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) {
                rhs_has_group = true;
-               rhs_leader_idx = rhs_core->leader->idx;
+               rhs_sort_idx = rhs_core->leader->idx;
+       } else {
+               rhs_has_group = false;
+               rhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(rhs)
+                       ? *force_grouped_idx
+                       : rhs_core->idx;
        }
 
-       if (lhs_leader_idx != rhs_leader_idx)
-               return lhs_leader_idx - rhs_leader_idx;
+       if (lhs_sort_idx != rhs_sort_idx)
+               return lhs_sort_idx - rhs_sort_idx;
 
        /* Group by PMU if there is a group. Groups can't span PMUs. */
        if (lhs_has_group && rhs_has_group) {
@@ -2146,10 +2156,10 @@ static int evlist__cmp(void *state, const struct list_head *l, const struct list
 
 static int parse_events__sort_events_and_fix_groups(struct list_head *list)
 {
-       int idx = 0, unsorted_idx = -1;
+       int idx = 0, force_grouped_idx = -1;
        struct evsel *pos, *cur_leader = NULL;
        struct perf_evsel *cur_leaders_grp = NULL;
-       bool idx_changed = false;
+       bool idx_changed = false, cur_leader_force_grouped = false;
        int orig_num_leaders = 0, num_leaders = 0;
        int ret;
 
@@ -2174,12 +2184,14 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
                 */
                pos->core.idx = idx++;
 
-               if (unsorted_idx == -1 && pos == pos_leader && pos->core.nr_members < 2)
-                       unsorted_idx = pos->core.idx;
+               /* Remember an index to sort all forced grouped events together to. */
+               if (force_grouped_idx == -1 && pos == pos_leader && pos->core.nr_members < 2 &&
+                   arch_evsel__must_be_in_group(pos))
+                       force_grouped_idx = pos->core.idx;
        }
 
        /* Sort events. */
-       list_sort(&unsorted_idx, list, evlist__cmp);
+       list_sort(&force_grouped_idx, list, evlist__cmp);
 
        /*
         * Recompute groups, splitting for PMUs and adding groups for events
@@ -2189,8 +2201,9 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
        list_for_each_entry(pos, list, core.node) {
                const struct evsel *pos_leader = evsel__leader(pos);
                const char *pos_pmu_name = pos->group_pmu_name;
-               const char *cur_leader_pmu_name, *pos_leader_pmu_name;
-               bool force_grouped = arch_evsel__must_be_in_group(pos);
+               const char *cur_leader_pmu_name;
+               bool pos_force_grouped = force_grouped_idx != -1 &&
+                       arch_evsel__must_be_in_group(pos);
 
                /* Reset index and nr_members. */
                if (pos->core.idx != idx)
@@ -2206,7 +2219,8 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
                        cur_leader = pos;
 
                cur_leader_pmu_name = cur_leader->group_pmu_name;
-               if ((cur_leaders_grp != pos->core.leader && !force_grouped) ||
+               if ((cur_leaders_grp != pos->core.leader &&
+                    (!pos_force_grouped || !cur_leader_force_grouped)) ||
                    strcmp(cur_leader_pmu_name, pos_pmu_name)) {
                        /* Event is for a different group/PMU than last. */
                        cur_leader = pos;
@@ -2216,14 +2230,14 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
                         * group.
                         */
                        cur_leaders_grp = pos->core.leader;
-               }
-               pos_leader_pmu_name = pos_leader->group_pmu_name;
-               if (strcmp(pos_leader_pmu_name, pos_pmu_name) || force_grouped) {
                        /*
-                        * Event's PMU differs from its leader's. Groups can't
-                        * span PMUs, so update leader from the group/PMU
-                        * tracker.
+                        * Avoid forcing events into groups with events that
+                        * don't need to be in the group.
                         */
+                       cur_leader_force_grouped = pos_force_grouped;
+               }
+               if (pos_leader != cur_leader) {
+                       /* The leader changed so update it. */
                        evsel__set_leader(pos, cur_leader);
                }
        }
index 7f984a7f16ca2636120dd547720113f8774a66ee..28380e7aa8d01b02aaa688165a375b2918319361 100644 (file)
@@ -1440,6 +1440,17 @@ void perf_pmu__del_formats(struct list_head *formats)
        }
 }
 
+bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name)
+{
+       struct perf_pmu_format *format;
+
+       list_for_each_entry(format, &pmu->format, list) {
+               if (!strcmp(format->name, name))
+                       return true;
+       }
+       return false;
+}
+
 bool is_pmu_core(const char *name)
 {
        return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name);
index 203b92860e3cec8cdc940e477b6a606d509c9f42..6b414cecbad221d6034a31ababeef6c2718dd3f8 100644 (file)
@@ -234,6 +234,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
 void perf_pmu__set_format(unsigned long *bits, long from, long to);
 int perf_pmu__format_parse(int dirfd, struct list_head *head);
 void perf_pmu__del_formats(struct list_head *formats);
+bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name);
 
 bool is_pmu_core(const char *name);
 bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu);
index 3cd9de42139ea77f0733b8c9c0728ffcf69277f1..c58ba9fb6a3697da4f4838ee5ad154930004064e 100644 (file)
@@ -152,16 +152,14 @@ static void pmu_read_sysfs(bool core_only)
        }
 
        closedir(dir);
-       if (core_only) {
-               if (!list_empty(&core_pmus))
-                       read_sysfs_core_pmus = true;
-               else {
-                       if (perf_pmu__create_placeholder_core_pmu(&core_pmus))
-                               read_sysfs_core_pmus = true;
-               }
-       } else {
+       if (list_empty(&core_pmus)) {
+               if (!perf_pmu__create_placeholder_core_pmu(&core_pmus))
+                       pr_err("Failure to set up any core PMUs\n");
+       }
+       if (!list_empty(&core_pmus)) {
                read_sysfs_core_pmus = true;
-               read_sysfs_all_pmus = true;
+               if (!core_only)
+                       read_sysfs_all_pmus = true;
        }
 }
 
index 7329b3340f889d05e317118481dae95b1e49516e..d45d5dcb0e2b506b52585770af9dda1a85600adc 100644 (file)
@@ -931,6 +931,11 @@ static bool should_skip_zero_counter(struct perf_stat_config *config,
         */
        if (config->aggr_mode == AGGR_THREAD && config->system_wide)
                return true;
+
+       /* Tool events have the software PMU but are only gathered on 1. */
+       if (evsel__is_tool(counter))
+               return true;
+
        /*
         * Skip value 0 when it's an uncore event and the given aggr id
         * does not belong to the PMU cpumask.
index 374d142e7390d1161255313919e0d7f378de3c12..c6a0a27b12c2a4fcfce7d0bbd42aed85d02ae7db 100644 (file)
@@ -1038,9 +1038,7 @@ static int thread_stack__trace_end(struct thread_stack *ts,
 
 static bool is_x86_retpoline(const char *name)
 {
-       const char *p = strstr(name, "__x86_indirect_thunk_");
-
-       return p == name || !strcmp(name, "__indirect_thunk_start");
+       return strstr(name, "__x86_indirect_thunk_") == name;
 }
 
 /*
index a61c7bcbc72da4bd022178f02a5ee90b3aa8f514..63f468bf8245cb70914a646eae59c2fd2aade8a8 100644 (file)
@@ -177,7 +177,7 @@ void regression1_test(void)
        nr_threads = 2;
        pthread_barrier_init(&worker_barrier, NULL, nr_threads);
 
-       threads = malloc(nr_threads * sizeof(pthread_t *));
+       threads = malloc(nr_threads * sizeof(*threads));
 
        for (i = 0; i < nr_threads; i++) {
                arg = i;
index b4f6f3a50ae5836ba8a50dbffc6aea7542cd77fd..5674a9d0cacf0e5b7b216e88064224b8b9ab047f 100644 (file)
@@ -869,6 +869,77 @@ static void test_msg_redir_to_listening(struct test_sockmap_listen *skel,
        xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT);
 }
 
+static void redir_partial(int family, int sotype, int sock_map, int parser_map)
+{
+       int s, c0, c1, p0, p1;
+       int err, n, key, value;
+       char buf[] = "abc";
+
+       key = 0;
+       value = sizeof(buf) - 1;
+       err = xbpf_map_update_elem(parser_map, &key, &value, 0);
+       if (err)
+               return;
+
+       s = socket_loopback(family, sotype | SOCK_NONBLOCK);
+       if (s < 0)
+               goto clean_parser_map;
+
+       err = create_socket_pairs(s, family, sotype, &c0, &c1, &p0, &p1);
+       if (err)
+               goto close_srv;
+
+       err = add_to_sockmap(sock_map, p0, p1);
+       if (err)
+               goto close;
+
+       n = xsend(c1, buf, sizeof(buf), 0);
+       if (n < sizeof(buf))
+               FAIL("incomplete write");
+
+       n = xrecv_nonblock(c0, buf, sizeof(buf), 0);
+       if (n != sizeof(buf) - 1)
+               FAIL("expect %zu, received %d", sizeof(buf) - 1, n);
+
+close:
+       xclose(c0);
+       xclose(p0);
+       xclose(c1);
+       xclose(p1);
+close_srv:
+       xclose(s);
+
+clean_parser_map:
+       key = 0;
+       value = 0;
+       xbpf_map_update_elem(parser_map, &key, &value, 0);
+}
+
+static void test_skb_redir_partial(struct test_sockmap_listen *skel,
+                                  struct bpf_map *inner_map, int family,
+                                  int sotype)
+{
+       int verdict = bpf_program__fd(skel->progs.prog_stream_verdict);
+       int parser = bpf_program__fd(skel->progs.prog_stream_parser);
+       int parser_map = bpf_map__fd(skel->maps.parser_map);
+       int sock_map = bpf_map__fd(inner_map);
+       int err;
+
+       err = xbpf_prog_attach(parser, sock_map, BPF_SK_SKB_STREAM_PARSER, 0);
+       if (err)
+               return;
+
+       err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT, 0);
+       if (err)
+               goto detach;
+
+       redir_partial(family, sotype, sock_map, parser_map);
+
+       xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT);
+detach:
+       xbpf_prog_detach2(parser, sock_map, BPF_SK_SKB_STREAM_PARSER);
+}
+
 static void test_reuseport_select_listening(int family, int sotype,
                                            int sock_map, int verd_map,
                                            int reuseport_prog)
@@ -1243,6 +1314,7 @@ static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map,
        } tests[] = {
                TEST(test_skb_redir_to_connected),
                TEST(test_skb_redir_to_listening),
+               TEST(test_skb_redir_partial),
                TEST(test_msg_redir_to_connected),
                TEST(test_msg_redir_to_listening),
        };
@@ -1432,7 +1504,7 @@ static void vsock_unix_redir_connectible(int sock_mapfd, int verd_mapfd,
        if (n < 1)
                goto out;
 
-       n = recv(mode == REDIR_INGRESS ? u0 : u1, &b, sizeof(b), MSG_DONTWAIT);
+       n = xrecv_nonblock(mode == REDIR_INGRESS ? u0 : u1, &b, sizeof(b), 0);
        if (n < 0)
                FAIL("%s: recv() err, errno=%d", log_prefix, errno);
        if (n == 0)
index 325c9f193432aaa0b2efeb62088389c91b52d2c2..464d35bd57c708a748163d71089ee329a76b56e1 100644 (file)
@@ -28,12 +28,26 @@ struct {
        __type(value, unsigned int);
 } verdict_map SEC(".maps");
 
+struct {
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+       __uint(max_entries, 1);
+       __type(key, int);
+       __type(value, int);
+} parser_map SEC(".maps");
+
 bool test_sockmap = false; /* toggled by user-space */
 bool test_ingress = false; /* toggled by user-space */
 
 SEC("sk_skb/stream_parser")
 int prog_stream_parser(struct __sk_buff *skb)
 {
+       int *value;
+       __u32 key = 0;
+
+       value = bpf_map_lookup_elem(&parser_map, &key);
+       if (value && *value)
+               return *value;
+
        return skb->len;
 }
 
index 258ddc565debaaa47f67284bdbccba81ecd5faf0..1b2cec9d18a42b4acdb1208b0d6f1d51bc18a888 100644 (file)
@@ -70,6 +70,10 @@ static int test_kmem_basic(const char *root)
                goto cleanup;
 
        cg_write(cg, "memory.high", "1M");
+
+       /* wait for RCU freeing */
+       sleep(1);
+
        slab1 = cg_read_key_long(cg, "memory.stat", "slab ");
        if (slab1 <= 0)
                goto cleanup;
index 435acebdc325f2e3fe7f56a23545387bd7bdbae6..380b691d3eb9fbe9c1070937d9561b732343aec0 100644 (file)
@@ -831,6 +831,7 @@ int main(int argc, char *argv[])
                                printf("Size must be greater than 0\n");
                                return KSFT_FAIL;
                        }
+                       break;
                case 't':
                        {
                                int tmp = atoi(optarg);
index 0f5e88c8f4ffece3833aab1929a119b22a9e063f..df8d90b51867a981897fa4bfc55269c70fffb072 100755 (executable)
@@ -1981,6 +1981,11 @@ basic()
 
        run_cmd "$IP link set dev lo up"
 
+       # Dump should not loop endlessly when maximum nexthop ID is configured.
+       run_cmd "$IP nexthop add id $((2**32-1)) blackhole"
+       run_cmd "timeout 5 $IP nexthop"
+       log_test $? 0 "Maximum nexthop ID dump"
+
        #
        # groups
        #
@@ -2201,6 +2206,11 @@ basic_res()
        run_cmd "$IP nexthop bucket list fdb"
        log_test $? 255 "Dump all nexthop buckets with invalid 'fdb' keyword"
 
+       # Dump should not loop endlessly when maximum nexthop ID is configured.
+       run_cmd "$IP nexthop add id $((2**32-1)) group 1/2 type resilient buckets 4"
+       run_cmd "timeout 5 $IP nexthop bucket"
+       log_test $? 0 "Maximum nexthop ID dump"
+
        #
        # resilient nexthop buckets get requests
        #
index ae3f9462a2b6147d78a5989a2fd257f5a90f7901..d0c6c499d5dab9852df8a15eb8244dd1a9230f9a 100755 (executable)
@@ -617,7 +617,7 @@ __cfg_test_port_ip_sg()
                grep -q "permanent"
        check_err $? "Entry not added as \"permanent\" when should"
        bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \
-               grep -q "0.00"
+               grep -q " 0.00"
        check_err $? "\"permanent\" entry has a pending group timer"
        bridge mdb del dev br0 port $swp1 $grp_key vid 10
 
@@ -626,7 +626,7 @@ __cfg_test_port_ip_sg()
                grep -q "temp"
        check_err $? "Entry not added as \"temp\" when should"
        bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \
-               grep -q "0.00"
+               grep -q " 0.00"
        check_fail $? "\"temp\" entry has an unpending group timer"
        bridge mdb del dev br0 port $swp1 $grp_key vid 10
 
@@ -659,7 +659,7 @@ __cfg_test_port_ip_sg()
                grep -q "permanent"
        check_err $? "Entry not marked as \"permanent\" after replace"
        bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \
-               grep -q "0.00"
+               grep -q " 0.00"
        check_err $? "Entry has a pending group timer after replace"
 
        bridge mdb replace dev br0 port $swp1 $grp_key vid 10 temp
@@ -667,7 +667,7 @@ __cfg_test_port_ip_sg()
                grep -q "temp"
        check_err $? "Entry not marked as \"temp\" after replace"
        bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \
-               grep -q "0.00"
+               grep -q " 0.00"
        check_fail $? "Entry has an unpending group timer after replace"
        bridge mdb del dev br0 port $swp1 $grp_key vid 10
 
@@ -850,6 +850,7 @@ cfg_test()
 __fwd_test_host_ip()
 {
        local grp=$1; shift
+       local dmac=$1; shift
        local src=$1; shift
        local mode=$1; shift
        local name
@@ -872,27 +873,27 @@ __fwd_test_host_ip()
        # Packet should only be flooded to multicast router ports when there is
        # no matching MDB entry. The bridge is not configured as a multicast
        # router port.
-       $MZ $mode $h1.10 -c 1 -p 128 -A $src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $src -B $grp -t udp -q
        tc_check_packets "dev br0 ingress" 1 0
        check_err $? "Packet locally received after flood"
 
        # Install a regular port group entry and expect the packet to not be
        # locally received.
        bridge mdb add dev br0 port $swp2 grp $grp temp vid 10
-       $MZ $mode $h1.10 -c 1 -p 128 -A $src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $src -B $grp -t udp -q
        tc_check_packets "dev br0 ingress" 1 0
        check_err $? "Packet locally received after installing a regular entry"
 
        # Add a host entry and expect the packet to be locally received.
        bridge mdb add dev br0 port br0 grp $grp temp vid 10
-       $MZ $mode $h1.10 -c 1 -p 128 -A $src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $src -B $grp -t udp -q
        tc_check_packets "dev br0 ingress" 1 1
        check_err $? "Packet not locally received after adding a host entry"
 
        # Remove the host entry and expect the packet to not be locally
        # received.
        bridge mdb del dev br0 port br0 grp $grp vid 10
-       $MZ $mode $h1.10 -c 1 -p 128 -A $src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $src -B $grp -t udp -q
        tc_check_packets "dev br0 ingress" 1 1
        check_err $? "Packet locally received after removing a host entry"
 
@@ -905,8 +906,8 @@ __fwd_test_host_ip()
 
 fwd_test_host_ip()
 {
-       __fwd_test_host_ip "239.1.1.1" "192.0.2.1" "-4"
-       __fwd_test_host_ip "ff0e::1" "2001:db8:1::1" "-6"
+       __fwd_test_host_ip "239.1.1.1" "01:00:5e:01:01:01" "192.0.2.1" "-4"
+       __fwd_test_host_ip "ff0e::1" "33:33:00:00:00:01" "2001:db8:1::1" "-6"
 }
 
 fwd_test_host_l2()
@@ -966,6 +967,7 @@ fwd_test_host()
 __fwd_test_port_ip()
 {
        local grp=$1; shift
+       local dmac=$1; shift
        local valid_src=$1; shift
        local invalid_src=$1; shift
        local mode=$1; shift
@@ -999,43 +1001,43 @@ __fwd_test_port_ip()
                vlan_ethtype $eth_type vlan_id 10 dst_ip $grp \
                src_ip $invalid_src action drop
 
-       $MZ $mode $h1.10 -c 1 -p 128 -A $valid_src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $valid_src -B $grp -t udp -q
        tc_check_packets "dev $h2 ingress" 1 0
        check_err $? "Packet from valid source received on H2 before adding entry"
 
-       $MZ $mode $h1.10 -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
        tc_check_packets "dev $h2 ingress" 2 0
        check_err $? "Packet from invalid source received on H2 before adding entry"
 
        bridge mdb add dev br0 port $swp2 grp $grp vid 10 \
                filter_mode $filter_mode source_list $src_list
 
-       $MZ $mode $h1.10 -c 1 -p 128 -A $valid_src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $valid_src -B $grp -t udp -q
        tc_check_packets "dev $h2 ingress" 1 1
        check_err $? "Packet from valid source not received on H2 after adding entry"
 
-       $MZ $mode $h1.10 -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
        tc_check_packets "dev $h2 ingress" 2 0
        check_err $? "Packet from invalid source received on H2 after adding entry"
 
        bridge mdb replace dev br0 port $swp2 grp $grp vid 10 \
                filter_mode exclude
 
-       $MZ $mode $h1.10 -c 1 -p 128 -A $valid_src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $valid_src -B $grp -t udp -q
        tc_check_packets "dev $h2 ingress" 1 2
        check_err $? "Packet from valid source not received on H2 after allowing all sources"
 
-       $MZ $mode $h1.10 -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
        tc_check_packets "dev $h2 ingress" 2 1
        check_err $? "Packet from invalid source not received on H2 after allowing all sources"
 
        bridge mdb del dev br0 port $swp2 grp $grp vid 10
 
-       $MZ $mode $h1.10 -c 1 -p 128 -A $valid_src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $valid_src -B $grp -t udp -q
        tc_check_packets "dev $h2 ingress" 1 2
        check_err $? "Packet from valid source received on H2 after deleting entry"
 
-       $MZ $mode $h1.10 -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
+       $MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
        tc_check_packets "dev $h2 ingress" 2 1
        check_err $? "Packet from invalid source received on H2 after deleting entry"
 
@@ -1047,11 +1049,11 @@ __fwd_test_port_ip()
 
 fwd_test_port_ip()
 {
-       __fwd_test_port_ip "239.1.1.1" "192.0.2.1" "192.0.2.2" "-4" "exclude"
-       __fwd_test_port_ip "ff0e::1" "2001:db8:1::1" "2001:db8:1::2" "-6" \
+       __fwd_test_port_ip "239.1.1.1" "01:00:5e:01:01:01" "192.0.2.1" "192.0.2.2" "-4" "exclude"
+       __fwd_test_port_ip "ff0e::1" "33:33:00:00:00:01" "2001:db8:1::1" "2001:db8:1::2" "-6" \
                "exclude"
-       __fwd_test_port_ip "239.1.1.1" "192.0.2.1" "192.0.2.2" "-4" "include"
-       __fwd_test_port_ip "ff0e::1" "2001:db8:1::1" "2001:db8:1::2" "-6" \
+       __fwd_test_port_ip "239.1.1.1" "01:00:5e:01:01:01" "192.0.2.1" "192.0.2.2" "-4" "include"
+       __fwd_test_port_ip "ff0e::1" "33:33:00:00:00:01" "2001:db8:1::1" "2001:db8:1::2" "-6" \
                "include"
 }
 
@@ -1127,7 +1129,7 @@ ctrl_igmpv3_is_in_test()
                filter_mode include source_list 192.0.2.1
 
        # IS_IN ( 192.0.2.2 )
-       $MZ $h1.10 -c 1 -A 192.0.2.1 -B 239.1.1.1 \
+       $MZ $h1.10 -c 1 -a own -b 01:00:5e:01:01:01 -A 192.0.2.1 -B 239.1.1.1 \
                -t ip proto=2,p=$(igmpv3_is_in_get 239.1.1.1 192.0.2.2) -q
 
        bridge -d mdb show dev br0 vid 10 | grep 239.1.1.1 | grep -q 192.0.2.2
@@ -1140,7 +1142,7 @@ ctrl_igmpv3_is_in_test()
                filter_mode include source_list 192.0.2.1
 
        # IS_IN ( 192.0.2.2 )
-       $MZ $h1.10 -c 1 -A 192.0.2.1 -B 239.1.1.1 \
+       $MZ $h1.10 -a own -b 01:00:5e:01:01:01 -c 1 -A 192.0.2.1 -B 239.1.1.1 \
                -t ip proto=2,p=$(igmpv3_is_in_get 239.1.1.1 192.0.2.2) -q
 
        bridge -d mdb show dev br0 vid 10 | grep 239.1.1.1 | grep -v "src" | \
@@ -1167,7 +1169,7 @@ ctrl_mldv2_is_in_test()
 
        # IS_IN ( 2001:db8:1::2 )
        local p=$(mldv2_is_in_get fe80::1 ff0e::1 2001:db8:1::2)
-       $MZ -6 $h1.10 -c 1 -A fe80::1 -B ff0e::1 \
+       $MZ -6 $h1.10 -a own -b 33:33:00:00:00:01 -c 1 -A fe80::1 -B ff0e::1 \
                -t ip hop=1,next=0,p="$p" -q
 
        bridge -d mdb show dev br0 vid 10 | grep ff0e::1 | \
@@ -1181,7 +1183,7 @@ ctrl_mldv2_is_in_test()
                filter_mode include source_list 2001:db8:1::1
 
        # IS_IN ( 2001:db8:1::2 )
-       $MZ -6 $h1.10 -c 1 -A fe80::1 -B ff0e::1 \
+       $MZ -6 $h1.10 -a own -b 33:33:00:00:00:01 -c 1 -A fe80::1 -B ff0e::1 \
                -t ip hop=1,next=0,p="$p" -q
 
        bridge -d mdb show dev br0 vid 10 | grep ff0e::1 | grep -v "src" | \
@@ -1206,6 +1208,11 @@ ctrl_test()
        ctrl_mldv2_is_in_test
 }
 
+if ! bridge mdb help 2>&1 | grep -q "replace"; then
+       echo "SKIP: iproute2 too old, missing bridge mdb replace support"
+       exit $ksft_skip
+fi
+
 trap cleanup EXIT
 
 setup_prepare
index ae255b662ba38b324d437ede643889882e070bbe..3da9d93ab36fb9b6cea1160a9889ee4869f84623 100755 (executable)
@@ -252,7 +252,8 @@ ctl4_entries_add()
        local IPs=$(seq -f 192.0.2.%g 1 $((n - 1)))
        local peer=$(locus_dev_peer $locus)
        local GRP=239.1.1.${grp}
-       $MZ $peer -c 1 -A 192.0.2.1 -B $GRP \
+       local dmac=01:00:5e:01:01:$(printf "%02x" $grp)
+       $MZ $peer -a own -b $dmac -c 1 -A 192.0.2.1 -B $GRP \
                -t ip proto=2,p=$(igmpv3_is_in_get $GRP $IPs) -q
        sleep 1
 
@@ -272,7 +273,8 @@ ctl4_entries_del()
 
        local peer=$(locus_dev_peer $locus)
        local GRP=239.1.1.${grp}
-       $MZ $peer -c 1 -A 192.0.2.1 -B 224.0.0.2 \
+       local dmac=01:00:5e:00:00:02
+       $MZ $peer -a own -b $dmac -c 1 -A 192.0.2.1 -B 224.0.0.2 \
                -t ip proto=2,p=$(igmpv2_leave_get $GRP) -q
        sleep 1
        ! bridge mdb show dev br0 | grep -q $GRP
@@ -289,8 +291,10 @@ ctl6_entries_add()
        local peer=$(locus_dev_peer $locus)
        local SIP=fe80::1
        local GRP=ff0e::${grp}
+       local dmac=33:33:00:00:00:$(printf "%02x" $grp)
        local p=$(mldv2_is_in_get $SIP $GRP $IPs)
-       $MZ -6 $peer -c 1 -A $SIP -B $GRP -t ip hop=1,next=0,p="$p" -q
+       $MZ -6 $peer -a own -b $dmac -c 1 -A $SIP -B $GRP \
+               -t ip hop=1,next=0,p="$p" -q
        sleep 1
 
        local nn=$(bridge mdb show dev br0 | grep $GRP | wc -l)
@@ -310,8 +314,10 @@ ctl6_entries_del()
        local peer=$(locus_dev_peer $locus)
        local SIP=fe80::1
        local GRP=ff0e::${grp}
+       local dmac=33:33:00:00:00:$(printf "%02x" $grp)
        local p=$(mldv1_done_get $SIP $GRP)
-       $MZ -6 $peer -c 1 -A $SIP -B $GRP -t ip hop=1,next=0,p="$p" -q
+       $MZ -6 $peer -a own -b $dmac -c 1 -A $SIP -B $GRP \
+               -t ip hop=1,next=0,p="$p" -q
        sleep 1
        ! bridge mdb show dev br0 | grep -q $GRP
 }
@@ -1328,6 +1334,11 @@ test_8021qvs()
        switch_destroy
 }
 
+if ! bridge link help 2>&1 | grep -q "mcast_max_groups"; then
+       echo "SKIP: iproute2 too old, missing bridge \"mcast_max_groups\" support"
+       exit $ksft_skip
+fi
+
 trap cleanup EXIT
 
 setup_prepare
index dbb9fcf759e0fbad7e1bd8c39a693590719a2e51..aa2eafb7b2437652e1e73745887a4794a7b596f3 100755 (executable)
@@ -286,6 +286,8 @@ different_speeds_autoneg_on()
        ethtool -s $h1 autoneg on
 }
 
+skip_on_veth
+
 trap cleanup EXIT
 
 setup_prepare
index 072faa77f53bd3bf3214ecb1c995c68d44596ed3..17f89c3b7c020676092ac81bc4c6db038386e9a1 100755 (executable)
@@ -108,6 +108,8 @@ no_cable()
        ip link set dev $swp3 down
 }
 
+skip_on_veth
+
 setup_prepare
 
 tests_run
index c580ad62384836857a06a574add5a5111f1bb438..39e736f30322aa1b89e0b603139bb5c893f35bf0 100755 (executable)
@@ -258,11 +258,6 @@ h2_destroy()
 
 setup_prepare()
 {
-       check_ethtool_mm_support
-       check_tc_fp_support
-       require_command lldptool
-       bail_on_lldpad "autoconfigure the MAC Merge layer" "configure it manually"
-
        h1=${NETIFS[p1]}
        h2=${NETIFS[p2]}
 
@@ -278,6 +273,19 @@ cleanup()
        h1_destroy
 }
 
+check_ethtool_mm_support
+check_tc_fp_support
+require_command lldptool
+bail_on_lldpad "autoconfigure the MAC Merge layer" "configure it manually"
+
+for netif in ${NETIFS[@]}; do
+       ethtool --show-mm $netif 2>&1 &> /dev/null
+       if [[ $? -ne 0 ]]; then
+               echo "SKIP: $netif does not support MAC Merge"
+               exit $ksft_skip
+       fi
+done
+
 trap cleanup EXIT
 
 setup_prepare
index eb9ec4a68f84bccea52fbfb43b12434605581343..7594bbb490292300418d7520e91f0191efde06a7 100755 (executable)
@@ -99,6 +99,8 @@ test_stats_rx()
        test_stats g2a rx
 }
 
+skip_on_veth
+
 trap cleanup EXIT
 
 setup_prepare
index 9f5b3e2e5e95467cfafbeda4df31331cbff9a72f..49fa94b53a1cac016147508473d4a50a1425fed7 100755 (executable)
@@ -14,6 +14,8 @@ ALL_TESTS="
 NUM_NETIFS=4
 source lib.sh
 
+require_command $TROUTE6
+
 h1_create()
 {
        simple_if_init $h1 2001:1:1::2/64
index 9ddb68dd6a089a42239554e4bd670000290f5b49..f69015bf2dea9ec714603c881ad2b0208e01b1c2 100755 (executable)
@@ -30,6 +30,7 @@ REQUIRE_MZ=${REQUIRE_MZ:=yes}
 REQUIRE_MTOOLS=${REQUIRE_MTOOLS:=no}
 STABLE_MAC_ADDRS=${STABLE_MAC_ADDRS:=no}
 TCPDUMP_EXTRA_FLAGS=${TCPDUMP_EXTRA_FLAGS:=}
+TROUTE6=${TROUTE6:=traceroute6}
 
 relative_path="${BASH_SOURCE%/*}"
 if [[ "$relative_path" == "${BASH_SOURCE}" ]]; then
@@ -163,6 +164,17 @@ check_port_mab_support()
        fi
 }
 
+skip_on_veth()
+{
+       local kind=$(ip -j -d link show dev ${NETIFS[p1]} |
+               jq -r '.[].linkinfo.info_kind')
+
+       if [[ $kind == veth ]]; then
+               echo "SKIP: Test cannot be run with veth pairs"
+               exit $ksft_skip
+       fi
+}
+
 if [[ "$(id -u)" -ne 0 ]]; then
        echo "SKIP: need root privileges"
        exit $ksft_skip
@@ -225,6 +237,11 @@ create_netif_veth()
        for ((i = 1; i <= NUM_NETIFS; ++i)); do
                local j=$((i+1))
 
+               if [ -z ${NETIFS[p$i]} ]; then
+                       echo "SKIP: Cannot create interface. Name not specified"
+                       exit $ksft_skip
+               fi
+
                ip link show dev ${NETIFS[p$i]} &> /dev/null
                if [[ $? -ne 0 ]]; then
                        ip link add ${NETIFS[p$i]} type veth \
index aff88f78e339152d67bd1d979bdd1d5c0cc471c3..5ea9d63915f77204ad1bb58a068774f377d31b0d 100755 (executable)
@@ -72,7 +72,8 @@ test_span_gre_ttl()
 
        RET=0
 
-       mirror_install $swp1 ingress $tundev "matchall $tcflags"
+       mirror_install $swp1 ingress $tundev \
+               "prot ip flower $tcflags ip_prot icmp"
        tc filter add dev $h3 ingress pref 77 prot $prot \
                flower skip_hw ip_ttl 50 action pass
 
diff --git a/tools/testing/selftests/net/forwarding/settings b/tools/testing/selftests/net/forwarding/settings
new file mode 100644 (file)
index 0000000..e7b9417
--- /dev/null
@@ -0,0 +1 @@
+timeout=0
index a96cff8e721975d2db4956798e8d6844e6fa870b..b0f5e55d2d0b2584aefacc135ffe6b2d2cab34fc 100755 (executable)
@@ -9,6 +9,8 @@ NUM_NETIFS=4
 source tc_common.sh
 source lib.sh
 
+require_command ncat
+
 tcflags="skip_hw"
 
 h1_create()
@@ -220,9 +222,9 @@ mirred_egress_to_ingress_tcp_test()
                ip_proto icmp \
                        action drop
 
-       ip vrf exec v$h1 nc --recv-only -w10 -l -p 12345 -o $mirred_e2i_tf2  &
+       ip vrf exec v$h1 ncat --recv-only -w10 -l -p 12345 -o $mirred_e2i_tf2 &
        local rpid=$!
-       ip vrf exec v$h1 nc -w1 --send-only 192.0.2.2 12345 <$mirred_e2i_tf1
+       ip vrf exec v$h1 ncat -w1 --send-only 192.0.2.2 12345 <$mirred_e2i_tf1
        wait -n $rpid
        cmp -s $mirred_e2i_tf1 $mirred_e2i_tf2
        check_err $? "server output check failed"
index 683711f41aa9b59f0559e0ba56851966e5189004..b1daad19b01ec7f75cd9d4870db2e3ada26b86b5 100755 (executable)
@@ -52,8 +52,8 @@ match_dst_mac_test()
        tc_check_packets "dev $h2 ingress" 101 1
        check_fail $? "Matched on a wrong filter"
 
-       tc_check_packets "dev $h2 ingress" 102 1
-       check_err $? "Did not match on correct filter"
+       tc_check_packets "dev $h2 ingress" 102 0
+       check_fail $? "Did not match on correct filter"
 
        tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
        tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
@@ -78,8 +78,8 @@ match_src_mac_test()
        tc_check_packets "dev $h2 ingress" 101 1
        check_fail $? "Matched on a wrong filter"
 
-       tc_check_packets "dev $h2 ingress" 102 1
-       check_err $? "Did not match on correct filter"
+       tc_check_packets "dev $h2 ingress" 102 0
+       check_fail $? "Did not match on correct filter"
 
        tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
        tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
index e22c2d28b6ebf385dc320975bfd1f863b563a447..20a7cb7222b8baa4062a769f2f0d27daf2b00cfd 100755 (executable)
@@ -127,6 +127,7 @@ test_l2_miss_multicast_common()
        local proto=$1; shift
        local sip=$1; shift
        local dip=$1; shift
+       local dmac=$1; shift
        local mode=$1; shift
        local name=$1; shift
 
@@ -142,7 +143,7 @@ test_l2_miss_multicast_common()
           action pass
 
        # Before adding MDB entry.
-       $MZ $mode $h1 -t ip -A $sip -B $dip -c 1 -p 100 -q
+       $MZ $mode $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
 
        tc_check_packets "dev $swp2 egress" 101 1
        check_err $? "Unregistered multicast filter was not hit before adding MDB entry"
@@ -153,7 +154,7 @@ test_l2_miss_multicast_common()
        # Adding MDB entry.
        bridge mdb replace dev br1 port $swp2 grp $dip permanent
 
-       $MZ $mode $h1 -t ip -A $sip -B $dip -c 1 -p 100 -q
+       $MZ $mode $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
 
        tc_check_packets "dev $swp2 egress" 101 1
        check_err $? "Unregistered multicast filter was hit after adding MDB entry"
@@ -164,7 +165,7 @@ test_l2_miss_multicast_common()
        # Deleting MDB entry.
        bridge mdb del dev br1 port $swp2 grp $dip
 
-       $MZ $mode $h1 -t ip -A $sip -B $dip -c 1 -p 100 -q
+       $MZ $mode $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
 
        tc_check_packets "dev $swp2 egress" 101 2
        check_err $? "Unregistered multicast filter was not hit after deleting MDB entry"
@@ -183,10 +184,11 @@ test_l2_miss_multicast_ipv4()
        local proto="ipv4"
        local sip=192.0.2.1
        local dip=239.1.1.1
+       local dmac=01:00:5e:01:01:01
        local mode="-4"
        local name="IPv4"
 
-       test_l2_miss_multicast_common $proto $sip $dip $mode $name
+       test_l2_miss_multicast_common $proto $sip $dip $dmac $mode $name
 }
 
 test_l2_miss_multicast_ipv6()
@@ -194,10 +196,11 @@ test_l2_miss_multicast_ipv6()
        local proto="ipv6"
        local sip=2001:db8:1::1
        local dip=ff0e::1
+       local dmac=33:33:00:00:00:01
        local mode="-6"
        local name="IPv6"
 
-       test_l2_miss_multicast_common $proto $sip $dip $mode $name
+       test_l2_miss_multicast_common $proto $sip $dip $dmac $mode $name
 }
 
 test_l2_miss_multicast()
index 5ac184d5180998cb7115c99106b0aa01109a2b2a..5a5dd90348195ca50f6dc955111f693ed4ee35cd 100755 (executable)
@@ -104,11 +104,14 @@ tunnel_key_nofrag_test()
        local i
 
        tc filter add dev $swp1 ingress protocol ip pref 100 handle 100 \
-               flower ip_flags nofrag action drop
+               flower src_ip 192.0.2.1 dst_ip 192.0.2.2 ip_proto udp \
+               ip_flags nofrag action drop
        tc filter add dev $swp1 ingress protocol ip pref 101 handle 101 \
-               flower ip_flags firstfrag action drop
+               flower src_ip 192.0.2.1 dst_ip 192.0.2.2 ip_proto udp \
+               ip_flags firstfrag action drop
        tc filter add dev $swp1 ingress protocol ip pref 102 handle 102 \
-               flower ip_flags nofirstfrag action drop
+               flower src_ip 192.0.2.1 dst_ip 192.0.2.2 ip_proto udp \
+               ip_flags nofirstfrag action drop
 
        # test 'nofrag' set
        tc filter add dev h1-et egress protocol all pref 1 handle 1 matchall $tcflags \
index 3c2096ac97ef48dda71d757d614d1db4ebcc5741..d01b73a8ed0f0eb07d12c333dceb6d7ce22c5298 100755 (executable)
@@ -705,6 +705,7 @@ pm_nl_del_endpoint()
        local addr=$3
 
        if [ $ip_mptcp -eq 1 ]; then
+               [ $id -ne 0 ] && addr=''
                ip -n $ns mptcp endpoint delete id $id $addr
        else
                ip netns exec $ns ./pm_nl_ctl del $id $addr
@@ -795,10 +796,11 @@ pm_nl_check_endpoint()
        fi
 
        if [ $ip_mptcp -eq 1 ]; then
+               # get line and trim trailing whitespace
                line=$(ip -n $ns mptcp endpoint show $id)
+               line="${line% }"
                # the dump order is: address id flags port dev
-               expected_line="$addr"
-               [ -n "$addr" ] && expected_line="$expected_line $addr"
+               [ -n "$addr" ] && expected_line="$addr"
                expected_line="$expected_line $id"
                [ -n "$_flags" ] && expected_line="$expected_line ${_flags//","/" "}"
                [ -n "$dev" ] && expected_line="$expected_line $dev"
index dfe3d287f01d24cdb9a1b538ff900e11b06e7d18..f838dd370f6af3ef252f0f77bf11e72aa80bed84 100755 (executable)
@@ -361,6 +361,7 @@ err_buf=
 tcpdump_pids=
 nettest_pids=
 socat_pids=
+tmpoutfile=
 
 err() {
        err_buf="${err_buf}${1}
@@ -951,6 +952,7 @@ cleanup() {
        ip link del veth_A-R1                   2>/dev/null
        ovs-vsctl --if-exists del-port vxlan_a  2>/dev/null
        ovs-vsctl --if-exists del-br ovs_br0    2>/dev/null
+       rm -f "$tmpoutfile"
 }
 
 mtu() {
@@ -1328,6 +1330,39 @@ test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception() {
        check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on bridged ${type} interface"
        pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst})"
        check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on locally bridged ${type} interface"
+
+       tmpoutfile=$(mktemp)
+
+       # Flush Exceptions, retry with TCP
+       run_cmd ${ns_a} ip route flush cached ${dst}
+       run_cmd ${ns_b} ip route flush cached ${dst}
+       run_cmd ${ns_c} ip route flush cached ${dst}
+
+       for target in "${ns_a}" "${ns_c}" ; do
+               if [ ${family} -eq 4 ]; then
+                       TCPDST=TCP:${dst}:50000
+               else
+                       TCPDST="TCP:[${dst}]:50000"
+               fi
+               ${ns_b} socat -T 3 -u -6 TCP-LISTEN:50000 STDOUT > $tmpoutfile &
+
+               sleep 1
+
+               dd if=/dev/zero of=/dev/stdout status=none bs=1M count=1 | ${target} socat -T 3 -u STDIN $TCPDST,connect-timeout=3
+
+               size=$(du -sb $tmpoutfile)
+               size=${size%%/tmp/*}
+
+               [ $size -ne 1048576 ] && err "File size $size mismatches exepcted value in locally bridged vxlan test" && return 1
+       done
+
+       rm -f "$tmpoutfile"
+
+       # Check that exceptions were created
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_c}" ${dst})"
+       check_pmtu_value ${exp_mtu} "${pmtu}" "tcp: exceeding link layer MTU on bridged ${type} interface"
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst})"
+       check_pmtu_value ${exp_mtu} "${pmtu}" "tcp exceeding link layer MTU on locally bridged ${type} interface"
 }
 
 test_pmtu_ipv4_br_vxlan4_exception() {
index 0e04f9fef9867967d3f0ec6dcd33bcc431a050f2..a148181641026e18e7d9c138ab7b6dde89cc90fd 100644 (file)
@@ -159,7 +159,7 @@ void create_clients(struct __test_metadata *_metadata,
                /* Make sure SYN will be processed on the i-th CPU
                 * and finally distributed to the i-th listener.
                 */
-               sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
+               ret = sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
                ASSERT_EQ(ret, 0);
 
                for (j = 0; j < CLIENT_PER_SERVER; j++) {
index 5cbc392944a6f926284fd9e7f15d1dbb96f9c6c8..2c0d2b1126c1e31db76fbd722bdf311bfbaafa9d 100644 (file)
@@ -1,6 +1,4 @@
 // SPDX-License-Identifier: GPL-2.0-only
-#include <sys/prctl.h>
-
 #define THIS_PROGRAM "./vstate_exec_nolibc"
 
 int main(int argc, char **argv)
index b357ba24af06f69cc03872ad5b6bb8b21273835e..7a957c7d459ae6f232b7071b51dadd92257cc218 100644 (file)
@@ -4,8 +4,10 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
 CLANG_FLAGS += -no-integrated-as
 endif
 
+top_srcdir = ../../../..
+
 CFLAGS += -O2 -Wall -g -I./ $(KHDR_INCLUDES) -L$(OUTPUT) -Wl,-rpath=./ \
-         $(CLANG_FLAGS)
+         $(CLANG_FLAGS) -I$(top_srcdir)/tools/include
 LDLIBS += -lpthread -ldl
 
 # Own dependencies because we only want to build against 1st prerequisite, but
index a723da2532441a8de60fe5e8f990c7bec0529727..96e812bdf8a45c7ad7cc0f8d1e8b2b26d6570722 100644 (file)
@@ -31,6 +31,8 @@
 #include <sys/auxv.h>
 #include <linux/auxvec.h>
 
+#include <linux/compiler.h>
+
 #include "../kselftest.h"
 #include "rseq.h"
 
index a44455372646ad9ee6c0a64a053a79e271125c8e..08d4861c2e78268d04c57b4fa398d7a82fef1dab 100644 (file)
         "teardown": [
             "echo \"1\" > /sys/bus/netdevsim/del_device"
         ]
+    },
+    {
+        "id": "3e1e",
+        "name": "Add taprio Qdisc with an invalid cycle-time",
+        "category": [
+            "qdisc",
+            "taprio"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "echo \"1 1 8\" > /sys/bus/netdevsim/new_device",
+            "$TC qdisc add dev $ETH root handle 1: taprio num_tc 3 map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 queues 1@0 1@0 1@0 base-time 1000000000 sched-entry S 01 300000 flags 0x1 clockid CLOCK_TAI cycle-time 4294967296 || /bin/true",
+            "$IP link set dev $ETH up",
+            "$IP addr add 10.10.10.10/24 dev $ETH"
+        ],
+        "cmdUnderTest": "/bin/true",
+        "expExitCode": "0",
+        "verifyCmd": "$TC qdisc show dev $ETH",
+        "matchPattern": "qdisc taprio 1: root refcnt",
+        "matchCount": "0",
+        "teardown": [
+            "echo \"1\" > /sys/bus/netdevsim/del_device"
+        ]
     }
 ]
index 43a254f0e14ddd14fe6fa8b7cca2a562b4bff009..21a98ba565ab5dba01aef8a53949bb966a424b07 100644 (file)
@@ -8,5 +8,5 @@ vsock_perf: vsock_perf.o
 CFLAGS += -g -O2 -Werror -Wall -I. -I../../include -I../../../usr/include -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -D_GNU_SOURCE
 .PHONY: all test clean
 clean:
-       ${RM} *.o *.d vsock_test vsock_diag_test
+       ${RM} *.o *.d vsock_test vsock_diag_test vsock_perf
 -include *.d