]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge tag 'char-misc-6.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 17 Feb 2024 16:52:38 +0000 (08:52 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 17 Feb 2024 16:52:38 +0000 (08:52 -0800)
Pull char / miscdriver fixes from Greg KH:
 "Here is a small set of char/misc and IIO driver fixes for 6.8-rc5.

  Included in here are:

   - lots of iio driver fixes for reported issues

   - nvmem device naming fixup for reported problem

   - interconnect driver fixes for reported issues

  All of these have been in linux-next for a while with no reported the
  issues (the nvmem patch was included in a different branch in
  linux-next before sent to me for inclusion here)"

* tag 'char-misc-6.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (21 commits)
  nvmem: include bit index in cell sysfs file name
  iio: adc: ad4130: only set GPIO_CTRL if pin is unused
  iio: adc: ad4130: zero-initialize clock init data
  interconnect: qcom: x1e80100: Add missing ACV enable_mask
  interconnect: qcom: sm8650: Use correct ACV enable_mask
  iio: accel: bma400: Fix a compilation problem
  iio: commom: st_sensors: ensure proper DMA alignment
  iio: hid-sensor-als: Return 0 for HID_USAGE_SENSOR_TIME_TIMESTAMP
  iio: move LIGHT_UVA and LIGHT_UVB to the end of iio_modifier
  staging: iio: ad5933: fix type mismatch regression
  iio: humidity: hdc3020: fix temperature offset
  iio: adc: ad7091r8: Fix error code in ad7091r8_gpio_setup()
  iio: adc: ad_sigma_delta: ensure proper DMA alignment
  iio: imu: adis: ensure proper DMA alignment
  iio: humidity: hdc3020: Add Makefile, Kconfig and MAINTAINERS entry
  iio: imu: bno055: serdev requires REGMAP
  iio: magnetometer: rm3100: add boundary check for the value read from RM3100_REG_TMRC
  iio: pressure: bmp280: Add missing bmp085 to SPI id table
  iio: core: fix memleak in iio_device_register_sysfs
  interconnect: qcom: sm8550: Enable sync_state
  ...

744 files changed:
.mailmap
Documentation/ABI/testing/sysfs-class-net-statistics
Documentation/arch/arm64/silicon-errata.rst
Documentation/devicetree/bindings/Makefile
Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml
Documentation/devicetree/bindings/display/bridge/nxp,tda998x.yaml
Documentation/devicetree/bindings/gpio/xlnx,zynqmp-gpio-modepin.yaml
Documentation/devicetree/bindings/net/marvell,prestera.yaml
Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.yaml
Documentation/devicetree/bindings/sound/google,sc7280-herobrine.yaml
Documentation/devicetree/bindings/tpm/tpm-common.yaml
Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml
Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml
Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
Documentation/devicetree/bindings/usb/xlnx,usb2.yaml
Documentation/netlink/specs/dpll.yaml
Documentation/networking/devlink/devlink-port.rst
Documentation/networking/net_cachelines/net_device.rst
Documentation/networking/net_cachelines/tcp_sock.rst
Documentation/sphinx/kernel_feat.py
MAINTAINERS
Makefile
arch/arc/include/asm/jump_label.h
arch/arm/include/asm/jump_label.h
arch/arm/mm/fault.c
arch/arm64/include/asm/alternative-macros.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/fpsimd.h
arch/arm64/include/asm/jump_label.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/signal.c
arch/arm64/kvm/Kconfig
arch/arm64/kvm/hyp/pgtable.c
arch/arm64/kvm/pkvm.c
arch/csky/include/asm/jump_label.h
arch/loongarch/Kconfig
arch/loongarch/include/asm/acpi.h
arch/loongarch/include/asm/jump_label.h
arch/loongarch/kernel/acpi.c
arch/loongarch/mm/kasan_init.c
arch/loongarch/vdso/Makefile
arch/mips/include/asm/checksum.h
arch/mips/include/asm/jump_label.h
arch/mips/include/asm/ptrace.h
arch/mips/kernel/ptrace.c
arch/parisc/include/asm/jump_label.h
arch/powerpc/include/asm/jump_label.h
arch/powerpc/include/asm/uaccess.h
arch/powerpc/kernel/irq_64.c
arch/riscv/include/asm/arch_hweight.h
arch/riscv/include/asm/bitops.h
arch/riscv/include/asm/checksum.h
arch/riscv/include/asm/cpufeature.h
arch/riscv/include/asm/hugetlb.h
arch/riscv/include/asm/jump_label.h
arch/riscv/include/asm/stacktrace.h
arch/riscv/include/asm/tlb.h
arch/riscv/include/asm/tlbflush.h
arch/riscv/include/uapi/asm/kvm.h
arch/riscv/kernel/paravirt.c
arch/riscv/kvm/vcpu_onereg.c
arch/riscv/kvm/vcpu_sbi_sta.c
arch/riscv/lib/csum.c
arch/riscv/mm/hugetlbpage.c
arch/riscv/mm/init.c
arch/riscv/mm/tlbflush.c
arch/s390/include/asm/jump_label.h
arch/s390/kvm/priv.c
arch/s390/kvm/vsie.c
arch/s390/mm/gmap.c
arch/sparc/include/asm/jump_label.h
arch/um/include/asm/cpufeature.h
arch/x86/Kconfig.cpu
arch/x86/boot/header.S
arch/x86/boot/setup.ld
arch/x86/include/asm/coco.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/jump_label.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/rmwcc.h
arch/x86/include/asm/special_insns.h
arch/x86/include/asm/uaccess.h
arch/x86/kernel/fpu/signal.c
arch/x86/kernel/kvm.c
arch/x86/kvm/hyperv.c
arch/x86/kvm/hyperv.h
arch/x86/kvm/svm/svm_ops.h
arch/x86/kvm/vmx/pmu_intel.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx_ops.h
arch/x86/kvm/x86.c
arch/x86/lib/getuser.S
arch/x86/lib/putuser.S
arch/x86/xen/smp.c
arch/xtensa/include/asm/jump_label.h
block/blk-iocost.c
block/blk-wbt.c
crypto/algif_hash.c
crypto/cbc.c
drivers/accel/ivpu/ivpu_drv.c
drivers/accel/ivpu/ivpu_fw.c
drivers/accel/ivpu/ivpu_hw_37xx.c
drivers/accel/ivpu/ivpu_hw_40xx.c
drivers/accel/ivpu/ivpu_job.c
drivers/accel/ivpu/ivpu_mmu.c
drivers/accel/ivpu/ivpu_pm.c
drivers/acpi/apei/ghes.c
drivers/atm/idt77252.c
drivers/base/regmap/regmap-kunit.c
drivers/block/virtio_blk.c
drivers/connector/cn_proc.c
drivers/crypto/ccp/sev-dev.c
drivers/cxl/core/trace.h
drivers/dpll/dpll_netlink.c
drivers/dpll/dpll_nl.c
drivers/dpll/dpll_nl.h
drivers/firewire/core-card.c
drivers/firmware/efi/arm-runtime.c
drivers/firmware/efi/cper.c
drivers/firmware/efi/efi-init.c
drivers/firmware/efi/libstub/Makefile
drivers/firmware/efi/libstub/alignedmem.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/kaslr.c
drivers/firmware/efi/libstub/randomalloc.c
drivers/firmware/efi/libstub/x86-stub.c
drivers/firmware/efi/libstub/x86-stub.h
drivers/firmware/efi/libstub/zboot.c
drivers/firmware/efi/riscv-runtime.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/soc21.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
drivers/gpu/drm/amd/amdkfd/kfd_process_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/dc/basics/dce_calcs.c
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_state.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c
drivers/gpu/drm/amd/display/dc/dml/Makefile
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
drivers/gpu/drm/amd/display/dc/inc/resource.h
drivers/gpu/drm/amd/display/dc/link/link_validation.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
drivers/gpu/drm/drm_buddy.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_vdsc_regs.h
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/intel_gvt.c
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
drivers/gpu/drm/msm/dp/dp_ctrl.c
drivers/gpu/drm/msm/dp/dp_link.c
drivers/gpu/drm/msm/dp/dp_reg.h
drivers/gpu/drm/msm/msm_gem_prime.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_iommu.c
drivers/gpu/drm/msm/msm_mdss.c
drivers/gpu/drm/msm/msm_ringbuffer.c
drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_abi16.h
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_exec.c
drivers/gpu/drm/nouveau/nouveau_sched.c
drivers/gpu/drm/nouveau/nouveau_sched.h
drivers/gpu/drm/nouveau/nouveau_svm.c
drivers/gpu/drm/nouveau/nouveau_uvmm.c
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/tests/drm_buddy_test.c
drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h
drivers/gpu/drm/xe/xe_display.c
drivers/gpu/drm/xe/xe_exec_queue.c
drivers/gpu/drm/xe/xe_gt.c
drivers/gpu/drm/xe/xe_gt_pagefault.c
drivers/gpu/drm/xe/xe_migrate.c
drivers/gpu/drm/xe/xe_pt.c
drivers/gpu/drm/xe/xe_pt_walk.c
drivers/gpu/drm/xe/xe_pt_walk.h
drivers/gpu/drm/xe/xe_range_fence.c
drivers/gpu/drm/xe/xe_sched_job.c
drivers/gpu/drm/xe/xe_sync.c
drivers/gpu/drm/xe/xe_vm.c
drivers/gpu/drm/xe/xe_vm_types.h
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-multitouch.c
drivers/hid/intel-ish-hid/ishtp/bus.c
drivers/hid/intel-ish-hid/ishtp/client.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hwmon/aspeed-pwm-tacho.c
drivers/hwmon/coretemp.c
drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
drivers/media/rc/Kconfig
drivers/media/rc/bpf-lirc.c
drivers/media/rc/ir_toy.c
drivers/media/rc/lirc_dev.c
drivers/media/rc/rc-core-priv.h
drivers/mmc/core/slot-gpio.c
drivers/mmc/host/sdhci-pci-o2micro.c
drivers/net/arcnet/arc-rawmode.c
drivers/net/arcnet/arc-rimi.c
drivers/net/arcnet/capmode.c
drivers/net/arcnet/com20020-pci.c
drivers/net/arcnet/com20020.c
drivers/net/arcnet/com20020_cs.c
drivers/net/arcnet/com90io.c
drivers/net/arcnet/com90xx.c
drivers/net/arcnet/rfc1051.c
drivers/net/arcnet/rfc1201.c
drivers/net/bonding/bond_main.c
drivers/net/can/dev/netlink.c
drivers/net/dsa/dsa_loop_bdinfo.c
drivers/net/ethernet/amd/pds_core/main.c
drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.h
drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/engleder/tsnep_main.c
drivers/net/ethernet/intel/i40e/i40e_dcb.c
drivers/net/ethernet/intel/i40e/i40e_dcb.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/ice/ice_lag.c
drivers/net/ethernet/intel/ice/ice_lag.h
drivers/net/ethernet/intel/ice/ice_osdep.h
drivers/net/ethernet/intel/ice/ice_type.h
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igc/igc_phy.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/mellanox/mlx5/core/dpll.c
drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
drivers/net/ethernet/pensando/ionic/ionic_txrx.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/cpsw_new.c
drivers/net/ethernet/ti/cpts.c
drivers/net/fddi/skfp/skfddi.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ieee802154/fakelb.c
drivers/net/ipvlan/ipvtap.c
drivers/net/netdevsim/dev.c
drivers/net/phy/mdio_devres.c
drivers/net/plip/plip.c
drivers/net/ppp/bsd_comp.c
drivers/net/ppp/ppp_async.c
drivers/net/ppp/ppp_deflate.c
drivers/net/ppp/ppp_generic.c
drivers/net/ppp/ppp_synctty.c
drivers/net/ppp/pppoe.c
drivers/net/wireless/ath/ar5523/ar5523.c
drivers/net/wireless/ath/wcn36xx/main.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/module.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/module.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/module.c
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/intersil/p54/p54spi.c
drivers/net/wireless/mediatek/mt76/mt7603/main.c
drivers/net/wireless/mediatek/mt76/mt7615/main.c
drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
drivers/net/wireless/mediatek/mt76/mt7615/usb.c
drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
drivers/net/wireless/mediatek/mt76/mt76x02_util.c
drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
drivers/net/wireless/mediatek/mt76/mt7921/main.c
drivers/net/wireless/mediatek/mt76/mt7921/pci.c
drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
drivers/net/wireless/mediatek/mt76/mt7921/usb.c
drivers/net/wireless/mediatek/mt76/mt7925/main.c
drivers/net/wireless/mediatek/mt76/mt7925/pci.c
drivers/net/wireless/mediatek/mt76/mt7925/usb.c
drivers/net/wireless/mediatek/mt76/mt792x_core.c
drivers/net/wireless/mediatek/mt76/mt792x_usb.c
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
drivers/net/wireless/mediatek/mt76/sdio.c
drivers/net/wireless/mediatek/mt76/usb.c
drivers/net/wireless/mediatek/mt76/util.c
drivers/net/wireless/microchip/wilc1000/netdev.c
drivers/net/wireless/microchip/wilc1000/sdio.c
drivers/net/wireless/microchip/wilc1000/spi.c
drivers/net/wireless/ti/wl1251/sdio.c
drivers/net/wireless/ti/wl1251/spi.c
drivers/net/wireless/ti/wl12xx/main.c
drivers/net/wireless/ti/wl18xx/main.c
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/sdio.c
drivers/net/wireless/ti/wlcore/spi.c
drivers/net/xen-netback/netback.c
drivers/nvme/host/core.c
drivers/nvme/host/fabrics.c
drivers/nvme/host/ioctl.c
drivers/nvme/host/nvme.h
drivers/nvme/host/sysfs.c
drivers/nvme/target/fabrics-cmd.c
drivers/of/property.c
drivers/of/unittest.c
drivers/pci/controller/dwc/pcie-designware-ep.c
drivers/pci/pci.c
drivers/perf/arm-cmn.c
drivers/perf/cxl_pmu.c
drivers/pinctrl/pinctrl-amd.c
drivers/pmdomain/core.c
drivers/pmdomain/mediatek/mtk-pm-domains.c
drivers/pmdomain/renesas/r8a77980-sysc.c
drivers/s390/net/qeth_l3_main.c
drivers/scsi/fcoe/fcoe_ctlr.c
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_fcs.c
drivers/scsi/fnic/fnic_main.c
drivers/scsi/fnic/fnic_scsi.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/spi/spi-imx.c
drivers/spi/spi-intel-pci.c
drivers/spi/spi-mxs.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-ppc4xx.c
drivers/staging/media/atomisp/pci/atomisp_cmd.c
drivers/staging/media/atomisp/pci/atomisp_internal.h
drivers/staging/media/atomisp/pci/atomisp_ioctl.c
drivers/staging/media/atomisp/pci/atomisp_v4l2.c
drivers/target/target_core_configfs.c
drivers/thunderbolt/tb_regs.h
drivers/thunderbolt/usb4.c
drivers/tty/serial/8250/8250_pci1xxxx.c
drivers/tty/serial/mxs-auart.c
drivers/ufs/core/ufshcd.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/gadget.h
drivers/xen/events/events_base.c
drivers/xen/gntalloc.c
drivers/xen/pcpu.c
drivers/xen/privcmd.c
drivers/xen/xen-balloon.c
drivers/xen/xenbus/xenbus_client.c
fs/bcachefs/fs-ioctl.c
fs/bcachefs/mean_and_variance.h
fs/bcachefs/thread_with_file.c
fs/bcachefs/util.c
fs/btrfs/block-group.c
fs/btrfs/block-group.h
fs/btrfs/delalloc-space.c
fs/btrfs/disk-io.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/send.c
fs/btrfs/transaction.c
fs/btrfs/zoned.c
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.h
fs/hugetlbfs/inode.c
fs/namespace.c
fs/nfsd/nfs4state.c
fs/nilfs2/file.c
fs/nilfs2/recovery.c
fs/nilfs2/segment.c
fs/ntfs3/attrib.c
fs/ntfs3/attrlist.c
fs/ntfs3/bitmap.c
fs/ntfs3/dir.c
fs/ntfs3/file.c
fs/ntfs3/frecord.c
fs/ntfs3/fslog.c
fs/ntfs3/fsntfs.c
fs/ntfs3/index.c
fs/ntfs3/inode.c
fs/ntfs3/namei.c
fs/ntfs3/ntfs.h
fs/ntfs3/ntfs_fs.h
fs/ntfs3/record.c
fs/ntfs3/super.c
fs/ntfs3/xattr.c
fs/overlayfs/copy_up.c
fs/proc/array.c
fs/remap_range.c
fs/smb/client/cached_dir.c
fs/smb/client/cifsglob.h
fs/smb/client/connect.c
fs/smb/client/dfs.c
fs/smb/client/file.c
fs/smb/client/fs_context.c
fs/smb/client/namespace.c
fs/smb/client/readdir.c
fs/smb/client/sess.c
fs/smb/client/smb2ops.c
fs/smb/client/smb2pdu.c
fs/smb/server/misc.c
fs/smb/server/smb2pdu.c
fs/zonefs/file.c
fs/zonefs/super.c
include/linux/backing-dev-defs.h
include/linux/ceph/messenger.h
include/linux/ceph/osd_client.h
include/linux/compiler-gcc.h
include/linux/compiler_types.h
include/linux/cper.h
include/linux/fs.h
include/linux/gpio/driver.h
include/linux/hrtimer.h
include/linux/netdevice.h
include/linux/nvme.h
include/linux/ptrace.h
include/linux/seq_buf.h
include/linux/serial_core.h
include/linux/tcp.h
include/linux/usb/gadget.h
include/net/cfg80211.h
include/net/netfilter/nf_tables.h
include/net/tls.h
include/sound/tas2781.h
include/trace/events/rxrpc.h
include/uapi/drm/ivpu_accel.h
include/uapi/linux/netfilter/nf_tables.h
include/uapi/xen/gntalloc.h
init/Kconfig
io_uring/net.c
kernel/exit.c
kernel/kprobes.c
kernel/sys.c
kernel/time/hrtimer.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_btf.c
kernel/trace/trace_events_synth.c
kernel/trace/trace_probe.c
kernel/trace/trace_probe.h
kernel/workqueue.c
lib/kunit/device-impl.h
lib/kunit/device.c
lib/kunit/test.c
lib/seq_buf.c
mm/backing-dev.c
mm/damon/sysfs-schemes.c
mm/madvise.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/page-writeback.c
mm/userfaultfd.c
mm/zswap.c
net/6lowpan/core.c
net/atm/mpc.c
net/can/j1939/j1939-priv.h
net/can/j1939/main.c
net/can/j1939/socket.c
net/ceph/messenger_v1.c
net/ceph/messenger_v2.c
net/ceph/osd_client.c
net/core/datagram.c
net/core/dev.c
net/core/rtnetlink.c
net/devlink/core.c
net/handshake/handshake-test.c
net/ipv4/af_inet.c
net/ipv4/ah4.c
net/ipv4/esp4.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_tunnel_core.c
net/ipv4/ip_vti.c
net/ipv4/ipip.c
net/ipv4/tcp.c
net/ipv4/tunnel4.c
net/ipv4/udp_tunnel_core.c
net/ipv4/xfrm4_tunnel.c
net/ipv6/ah6.c
net/ipv6/esp6.c
net/ipv6/ip6_output.c
net/ipv6/ip6_udp_tunnel.c
net/ipv6/mip6.c
net/ipv6/sit.c
net/ipv6/tunnel6.c
net/ipv6/xfrm6_tunnel.c
net/key/af_key.c
net/mac80211/cfg.c
net/mac80211/debugfs_netdev.c
net/mac80211/debugfs_netdev.h
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/scan.c
net/mac80211/tx.c
net/mac80211/wbrf.c
net/mptcp/fastopen.c
net/mptcp/options.c
net/mptcp/pm_userspace.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_nat_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_queue.c
net/netfilter/nft_compat.c
net/netfilter/nft_ct.c
net/netfilter/nft_flow_offload.c
net/netfilter/nft_set_hash.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_pipapo.h
net/netfilter/nft_set_pipapo_avx2.c
net/netfilter/nft_set_rbtree.c
net/openvswitch/flow_netlink.c
net/rds/recv.c
net/rxrpc/ar-internal.h
net/rxrpc/call_event.c
net/rxrpc/call_object.c
net/rxrpc/conn_event.c
net/rxrpc/input.c
net/rxrpc/output.c
net/rxrpc/proc.c
net/rxrpc/rxkad.c
net/sched/act_mirred.c
net/sched/em_canid.c
net/sched/em_cmp.c
net/sched/em_meta.c
net/sched/em_nbyte.c
net/sched/em_text.c
net/sched/em_u32.c
net/sctp/inqueue.c
net/smc/af_smc.c
net/tipc/bearer.c
net/tls/tls_sw.c
net/unix/garbage.c
net/wireless/core.c
net/wireless/scan.c
net/xfrm/xfrm_algo.c
net/xfrm/xfrm_user.c
samples/bpf/asm_goto_workaround.h
security/security.c
sound/pci/hda/Kconfig
sound/pci/hda/cs35l41_hda_property.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/tas2781_hda_i2c.c
sound/soc/amd/yc/acp6x-mach.c
sound/soc/codecs/cs35l56-shared.c
sound/soc/codecs/cs35l56.c
sound/soc/codecs/cs35l56.h
sound/soc/codecs/cs42l43.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/tas2781-comlib.c
sound/soc/codecs/tas2781-i2c.c
sound/soc/intel/avs/core.c
sound/soc/intel/avs/topology.c
sound/soc/intel/boards/bytcht_cx2072x.c
sound/soc/intel/boards/bytcht_da7213.c
sound/soc/intel/boards/bytcht_es8316.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/bytcr_rt5651.c
sound/soc/intel/boards/bytcr_wm5102.c
sound/soc/intel/boards/cht_bsw_rt5645.c
sound/soc/intel/boards/cht_bsw_rt5672.c
sound/soc/qcom/qdsp6/q6apm-dai.c
sound/soc/sof/amd/acp-ipc.c
sound/soc/sof/amd/acp.c
sound/soc/sof/intel/pci-lnl.c
sound/soc/sof/intel/pci-tgl.c
sound/soc/sof/ipc3-topology.c
sound/soc/sof/ipc3.c
sound/soc/sof/ipc4-pcm.c
sound/usb/midi.c
tools/arch/x86/include/asm/rmwcc.h
tools/include/linux/compiler_types.h
tools/testing/selftests/core/close_range_test.c
tools/testing/selftests/dt/test_unprobed_devices.sh
tools/testing/selftests/kvm/aarch64/arch_timer.c
tools/testing/selftests/kvm/aarch64/hypercalls.c
tools/testing/selftests/kvm/aarch64/page_fault_test.c
tools/testing/selftests/kvm/aarch64/smccc_filter.c
tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c
tools/testing/selftests/kvm/demand_paging_test.c
tools/testing/selftests/kvm/dirty_log_perf_test.c
tools/testing/selftests/kvm/dirty_log_test.c
tools/testing/selftests/kvm/get-reg-list.c
tools/testing/selftests/kvm/guest_print_test.c
tools/testing/selftests/kvm/hardware_disable_test.c
tools/testing/selftests/kvm/include/test_util.h
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/kvm_create_max_vcpus.c
tools/testing/selftests/kvm/kvm_page_table_test.c
tools/testing/selftests/kvm/lib/aarch64/processor.c
tools/testing/selftests/kvm/lib/aarch64/vgic.c
tools/testing/selftests/kvm/lib/elf.c
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/lib/memstress.c
tools/testing/selftests/kvm/lib/riscv/processor.c
tools/testing/selftests/kvm/lib/s390x/processor.c
tools/testing/selftests/kvm/lib/test_util.c
tools/testing/selftests/kvm/lib/userfaultfd_util.c
tools/testing/selftests/kvm/lib/x86_64/processor.c
tools/testing/selftests/kvm/lib/x86_64/vmx.c
tools/testing/selftests/kvm/memslot_modification_stress_test.c
tools/testing/selftests/kvm/memslot_perf_test.c
tools/testing/selftests/kvm/riscv/get-reg-list.c
tools/testing/selftests/kvm/rseq_test.c
tools/testing/selftests/kvm/s390x/resets.c
tools/testing/selftests/kvm/s390x/sync_regs_test.c
tools/testing/selftests/kvm/set_memory_region_test.c
tools/testing/selftests/kvm/system_counter_offset_test.c
tools/testing/selftests/kvm/x86_64/amx_test.c
tools/testing/selftests/kvm/x86_64/cpuid_test.c
tools/testing/selftests/kvm/x86_64/dirty_log_page_splitting_test.c
tools/testing/selftests/kvm/x86_64/flds_emulation.h
tools/testing/selftests/kvm/x86_64/hyperv_clock.c
tools/testing/selftests/kvm/x86_64/hyperv_features.c
tools/testing/selftests/kvm/x86_64/hyperv_ipi.c
tools/testing/selftests/kvm/x86_64/hyperv_tlb_flush.c
tools/testing/selftests/kvm/x86_64/kvm_clock_test.c
tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c
tools/testing/selftests/kvm/x86_64/platform_info_test.c
tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
tools/testing/selftests/kvm/x86_64/sev_migrate_tests.c
tools/testing/selftests/kvm/x86_64/smaller_maxphyaddr_emulation_test.c
tools/testing/selftests/kvm/x86_64/sync_regs_test.c
tools/testing/selftests/kvm/x86_64/ucna_injection_test.c
tools/testing/selftests/kvm/x86_64/userspace_io_test.c
tools/testing/selftests/kvm/x86_64/vmx_apic_access_test.c
tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c
tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c
tools/testing/selftests/kvm/x86_64/vmx_nested_tsc_scaling_test.c
tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c
tools/testing/selftests/kvm/x86_64/xcr0_cpuid_test.c
tools/testing/selftests/kvm/x86_64/xss_msr_test.c
tools/testing/selftests/landlock/common.h
tools/testing/selftests/landlock/fs_test.c
tools/testing/selftests/landlock/net_test.c
tools/testing/selftests/net/big_tcp.sh
tools/testing/selftests/net/cmsg_ipv6.sh
tools/testing/selftests/net/config
tools/testing/selftests/net/forwarding/bridge_locked_port.sh
tools/testing/selftests/net/forwarding/bridge_mdb.sh
tools/testing/selftests/net/forwarding/tc_flower_l2_miss.sh
tools/testing/selftests/net/gro.sh
tools/testing/selftests/net/ip_local_port_range.c
tools/testing/selftests/net/net_helper.sh
tools/testing/selftests/net/openvswitch/openvswitch.sh
tools/testing/selftests/net/openvswitch/ovs-dpctl.py
tools/testing/selftests/net/pmtu.sh
tools/testing/selftests/net/rtnetlink.sh
tools/testing/selftests/net/so_txtime.sh
tools/testing/selftests/net/tcp_ao/unsigned-md5.c
tools/testing/selftests/net/test_bridge_backup_port.sh
tools/testing/selftests/net/tls.c
tools/testing/selftests/net/udpgro_fwd.sh
tools/testing/selftests/net/udpgso_bench_rx.c
tools/testing/selftests/netfilter/conntrack_dump_flush.c
tools/tracing/rtla/Makefile
tools/tracing/rtla/src/osnoise_hist.c
tools/tracing/rtla/src/osnoise_top.c
tools/tracing/rtla/src/timerlat_hist.c
tools/tracing/rtla/src/timerlat_top.c
tools/tracing/rtla/src/utils.c
tools/tracing/rtla/src/utils.h
tools/verification/rv/Makefile
tools/verification/rv/src/in_kernel.c

index 04998f7bda81816b4bb1dd321f80393a80ae9a67..b99a238ee3bde17fdf4e0f6b9ca0aee81e1dc9a7 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -191,10 +191,11 @@ Gao Xiang <xiang@kernel.org> <gaoxiang25@huawei.com>
 Gao Xiang <xiang@kernel.org> <hsiangkao@aol.com>
 Gao Xiang <xiang@kernel.org> <hsiangkao@linux.alibaba.com>
 Gao Xiang <xiang@kernel.org> <hsiangkao@redhat.com>
-Geliang Tang <geliang.tang@linux.dev> <geliang.tang@suse.com>
-Geliang Tang <geliang.tang@linux.dev> <geliangtang@xiaomi.com>
-Geliang Tang <geliang.tang@linux.dev> <geliangtang@gmail.com>
-Geliang Tang <geliang.tang@linux.dev> <geliangtang@163.com>
+Geliang Tang <geliang@kernel.org> <geliang.tang@linux.dev>
+Geliang Tang <geliang@kernel.org> <geliang.tang@suse.com>
+Geliang Tang <geliang@kernel.org> <geliangtang@xiaomi.com>
+Geliang Tang <geliang@kernel.org> <geliangtang@gmail.com>
+Geliang Tang <geliang@kernel.org> <geliangtang@163.com>
 Georgi Djakov <djakov@kernel.org> <georgi.djakov@linaro.org>
 Gerald Schaefer <gerald.schaefer@linux.ibm.com> <geraldsc@de.ibm.com>
 Gerald Schaefer <gerald.schaefer@linux.ibm.com> <gerald.schaefer@de.ibm.com>
@@ -289,6 +290,7 @@ Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
 John Crispin <john@phrozen.org> <blogic@openwrt.org>
 John Fastabend <john.fastabend@gmail.com> <john.r.fastabend@intel.com>
 John Keeping <john@keeping.me.uk> <john@metanate.com>
+John Moon <john@jmoon.dev> <quic_johmoo@quicinc.com>
 John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
 John Stultz <johnstul@us.ibm.com>
 <jon.toppins+linux@gmail.com> <jtoppins@cumulusnetworks.com>
@@ -344,6 +346,7 @@ Leonid I Ananiev <leonid.i.ananiev@intel.com>
 Leon Romanovsky <leon@kernel.org> <leon@leon.nu>
 Leon Romanovsky <leon@kernel.org> <leonro@mellanox.com>
 Leon Romanovsky <leon@kernel.org> <leonro@nvidia.com>
+Leo Yan <leo.yan@linux.dev> <leo.yan@linaro.org>
 Liam Mark <quic_lmark@quicinc.com> <lmark@codeaurora.org>
 Linas Vepstas <linas@austin.ibm.com>
 Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch>
index 55db27815361b2d9ad511e026bee60a615ae03d5..53e508c6936a515216ad3af96ddfb170f6e50cf7 100644 (file)
@@ -1,4 +1,4 @@
-What:          /sys/class/<iface>/statistics/collisions
+What:          /sys/class/net/<iface>/statistics/collisions
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -6,7 +6,7 @@ Description:
                Indicates the number of collisions seen by this network device.
                This value might not be relevant with all MAC layers.
 
-What:          /sys/class/<iface>/statistics/multicast
+What:          /sys/class/net/<iface>/statistics/multicast
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -14,7 +14,7 @@ Description:
                Indicates the number of multicast packets received by this
                network device.
 
-What:          /sys/class/<iface>/statistics/rx_bytes
+What:          /sys/class/net/<iface>/statistics/rx_bytes
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -23,7 +23,7 @@ Description:
                See the network driver for the exact meaning of when this
                value is incremented.
 
-What:          /sys/class/<iface>/statistics/rx_compressed
+What:          /sys/class/net/<iface>/statistics/rx_compressed
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -32,7 +32,7 @@ Description:
                network device. This value might only be relevant for interfaces
                that support packet compression (e.g: PPP).
 
-What:          /sys/class/<iface>/statistics/rx_crc_errors
+What:          /sys/class/net/<iface>/statistics/rx_crc_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -41,7 +41,7 @@ Description:
                by this network device. Note that the specific meaning might
                depend on the MAC layer used by the interface.
 
-What:          /sys/class/<iface>/statistics/rx_dropped
+What:          /sys/class/net/<iface>/statistics/rx_dropped
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -51,7 +51,7 @@ Description:
                packet processing. See the network driver for the exact
                meaning of this value.
 
-What:          /sys/class/<iface>/statistics/rx_errors
+What:          /sys/class/net/<iface>/statistics/rx_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -59,7 +59,7 @@ Description:
                Indicates the number of receive errors on this network device.
                See the network driver for the exact meaning of this value.
 
-What:          /sys/class/<iface>/statistics/rx_fifo_errors
+What:          /sys/class/net/<iface>/statistics/rx_fifo_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -68,7 +68,7 @@ Description:
                network device. See the network driver for the exact
                meaning of this value.
 
-What:          /sys/class/<iface>/statistics/rx_frame_errors
+What:          /sys/class/net/<iface>/statistics/rx_frame_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -78,7 +78,7 @@ Description:
                on the MAC layer protocol used. See the network driver for
                the exact meaning of this value.
 
-What:          /sys/class/<iface>/statistics/rx_length_errors
+What:          /sys/class/net/<iface>/statistics/rx_length_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -87,7 +87,7 @@ Description:
                error, oversized or undersized. See the network driver for the
                exact meaning of this value.
 
-What:          /sys/class/<iface>/statistics/rx_missed_errors
+What:          /sys/class/net/<iface>/statistics/rx_missed_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -96,7 +96,7 @@ Description:
                due to lack of capacity in the receive side. See the network
                driver for the exact meaning of this value.
 
-What:          /sys/class/<iface>/statistics/rx_nohandler
+What:          /sys/class/net/<iface>/statistics/rx_nohandler
 Date:          February 2016
 KernelVersion: 4.6
 Contact:       netdev@vger.kernel.org
@@ -104,7 +104,7 @@ Description:
                Indicates the number of received packets that were dropped on
                an inactive device by the network core.
 
-What:          /sys/class/<iface>/statistics/rx_over_errors
+What:          /sys/class/net/<iface>/statistics/rx_over_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -114,7 +114,7 @@ Description:
                (e.g: larger than MTU). See the network driver for the exact
                meaning of this value.
 
-What:          /sys/class/<iface>/statistics/rx_packets
+What:          /sys/class/net/<iface>/statistics/rx_packets
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -122,7 +122,7 @@ Description:
                Indicates the total number of good packets received by this
                network device.
 
-What:          /sys/class/<iface>/statistics/tx_aborted_errors
+What:          /sys/class/net/<iface>/statistics/tx_aborted_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -132,7 +132,7 @@ Description:
                a medium collision). See the network driver for the exact
                meaning of this value.
 
-What:          /sys/class/<iface>/statistics/tx_bytes
+What:          /sys/class/net/<iface>/statistics/tx_bytes
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -143,7 +143,7 @@ Description:
                transmitted packets or all packets that have been queued for
                transmission.
 
-What:          /sys/class/<iface>/statistics/tx_carrier_errors
+What:          /sys/class/net/<iface>/statistics/tx_carrier_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -152,7 +152,7 @@ Description:
                because of carrier errors (e.g: physical link down). See the
                network driver for the exact meaning of this value.
 
-What:          /sys/class/<iface>/statistics/tx_compressed
+What:          /sys/class/net/<iface>/statistics/tx_compressed
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -161,7 +161,7 @@ Description:
                this might only be relevant for devices that support
                compression (e.g: PPP).
 
-What:          /sys/class/<iface>/statistics/tx_dropped
+What:          /sys/class/net/<iface>/statistics/tx_dropped
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -170,7 +170,7 @@ Description:
                See the driver for the exact reasons as to why the packets were
                dropped.
 
-What:          /sys/class/<iface>/statistics/tx_errors
+What:          /sys/class/net/<iface>/statistics/tx_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -179,7 +179,7 @@ Description:
                a network device. See the driver for the exact reasons as to
                why the packets were dropped.
 
-What:          /sys/class/<iface>/statistics/tx_fifo_errors
+What:          /sys/class/net/<iface>/statistics/tx_fifo_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -188,7 +188,7 @@ Description:
                FIFO error. See the driver for the exact reasons as to why the
                packets were dropped.
 
-What:          /sys/class/<iface>/statistics/tx_heartbeat_errors
+What:          /sys/class/net/<iface>/statistics/tx_heartbeat_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -197,7 +197,7 @@ Description:
                reported as heartbeat errors. See the driver for the exact
                reasons as to why the packets were dropped.
 
-What:          /sys/class/<iface>/statistics/tx_packets
+What:          /sys/class/net/<iface>/statistics/tx_packets
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
@@ -206,7 +206,7 @@ Description:
                device. See the driver for whether this reports the number of all
                attempted or successful transmissions.
 
-What:          /sys/class/<iface>/statistics/tx_window_errors
+What:          /sys/class/net/<iface>/statistics/tx_window_errors
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       netdev@vger.kernel.org
index e8c2ce1f9df68df5976b7cc536d3f48c0501ba4b..45a7f4932fe07f295cd452313bfcb64c59809218 100644 (file)
@@ -243,3 +243,10 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | ASR            | ASR8601         | #8601001        | N/A                         |
 +----------------+-----------------+-----------------+-----------------------------+
++----------------+-----------------+-----------------+-----------------------------+
+| Microsoft      | Azure Cobalt 100| #2139208        | ARM64_ERRATUM_2139208       |
++----------------+-----------------+-----------------+-----------------------------+
+| Microsoft      | Azure Cobalt 100| #2067961        | ARM64_ERRATUM_2067961       |
++----------------+-----------------+-----------------+-----------------------------+
+| Microsoft      | Azure Cobalt 100| #2253138        | ARM64_ERRATUM_2253138       |
++----------------+-----------------+-----------------+-----------------------------+
index 2323fd5b7cdae1ebe440275d8f67649354a6f448..129cf698fa8a66fd2be5111074319da545f4cc98 100644 (file)
@@ -28,7 +28,10 @@ $(obj)/%.example.dts: $(src)/%.yaml check_dtschema_version FORCE
 find_all_cmd = find $(srctree)/$(src) \( -name '*.yaml' ! \
                -name 'processed-schema*' \)
 
-find_cmd = $(find_all_cmd) | sed 's|^$(srctree)/$(src)/||' | grep -F -e "$(subst :," -e ",$(DT_SCHEMA_FILES))" | sed 's|^|$(srctree)/$(src)/|'
+find_cmd = $(find_all_cmd) | \
+               sed 's|^$(srctree)/||' | \
+               grep -F -e "$(subst :," -e ",$(DT_SCHEMA_FILES))" | \
+               sed 's|^|$(srctree)/|'
 CHK_DT_DOCS := $(shell $(find_cmd))
 
 quiet_cmd_yamllint = LINT    $(src)
index b29ce598f9aaea327bcd177dc6bf143ee8693ebf..9952e0ef77674c11d115dab50a904841410e148a 100644 (file)
@@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Ceva AHCI SATA Controller
 
 maintainers:
-  - Piyush Mehta <piyush.mehta@amd.com>
+  - Mubin Sayyed <mubin.sayyed@amd.com>
+  - Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
 
 description: |
   The Ceva SATA controller mostly conforms to the AHCI interface with some
index 21d995f29a1e3068be328506cf01d8f0f5d3d383..b8e9cf6ce4e61145bb6a30d90396b982449b2f08 100644 (file)
@@ -29,19 +29,22 @@ properties:
 
   audio-ports:
     description:
-      Array of 8-bit values, 2 values per DAI (Documentation/sound/soc/dai.rst).
+      Array of 2 values per DAI (Documentation/sound/soc/dai.rst).
       The implementation allows one or two DAIs.
       If two DAIs are defined, they must be of different type.
     $ref: /schemas/types.yaml#/definitions/uint32-matrix
+    minItems: 1
+    maxItems: 2
     items:
-      minItems: 1
       items:
         - description: |
             The first value defines the DAI type: TDA998x_SPDIF or TDA998x_I2S
             (see include/dt-bindings/display/tda998x.h).
+          enum: [ 1, 2 ]
         - description:
             The second value defines the tda998x AP_ENA reg content when the
             DAI in question is used.
+          maximum: 0xff
 
   '#sound-dai-cells':
     enum: [ 0, 1 ]
index b1fd632718d49659483fd7e6773377adeb66d938..bb93baa888794b83d1613cecca79a383b528914a 100644 (file)
@@ -12,7 +12,8 @@ description:
   PS_MODE). Every pin can be configured as input/output.
 
 maintainers:
-  - Piyush Mehta <piyush.mehta@amd.com>
+  - Mubin Sayyed <mubin.sayyed@amd.com>
+  - Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
 
 properties:
   compatible:
index 5ea8b73663a50c3f55999fb8cc911af491d46086..16ff892f7bbd0aa8f965d602e5ccbd3b18ec9253 100644 (file)
@@ -78,8 +78,8 @@ examples:
     pcie@0 {
         #address-cells = <3>;
         #size-cells = <2>;
-        ranges = <0x0 0x0 0x0 0x0 0x0 0x0>;
-        reg = <0x0 0x0 0x0 0x0 0x0 0x0>;
+        ranges = <0x02000000 0x0 0x100000 0x10000000 0x0 0x0>;
+        reg = <0x0 0x1000>;
         device_type = "pci";
 
         switch@0,0 {
index 49db668014297040f85b628137769951663992ed..1f1b42dde94d5086020f0a89d183eafa1ea17589 100644 (file)
@@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Zynq UltraScale+ MPSoC and Versal reset
 
 maintainers:
-  - Piyush Mehta <piyush.mehta@amd.com>
+  - Mubin Sayyed <mubin.sayyed@amd.com>
+  - Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
 
 description: |
   The Zynq UltraScale+ MPSoC and Versal has several different resets.
index ec4b6e547ca6efad4b77697c567e30da74707261..cdcd7c6f21eb241663c44fd8d066dc1700a8994b 100644 (file)
@@ -7,7 +7,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Google SC7280-Herobrine ASoC sound card driver
 
 maintainers:
-  - Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
   - Judy Hsiao <judyhsiao@chromium.org>
 
 description:
index 90390624a8be5e7abc0b18374f19705db999a97d..3c1241b2a43f99d361e0af89aed61f4318c9b914 100644 (file)
@@ -42,7 +42,7 @@ properties:
 
   resets:
     description: Reset controller to reset the TPM
-    $ref: /schemas/types.yaml#/definitions/phandle
+    maxItems: 1
 
   reset-gpios:
     description: Output GPIO pin to reset the TPM
index 88cc1e3a0c887c367c7ed83ff2a0835398a20b93..b2b509b3944d85714316c8f91b042054373416a4 100644 (file)
@@ -55,9 +55,12 @@ properties:
 
   samsung,sysreg:
     $ref: /schemas/types.yaml#/definitions/phandle-array
-    description: Should be phandle/offset pair. The phandle to the syscon node
-                 which indicates the FSYSx sysreg interface and the offset of
-                 the control register for UFS io coherency setting.
+    items:
+      - items:
+          - description: phandle to FSYSx sysreg node
+          - description: offset of the control register for UFS io coherency setting
+    description:
+      Phandle and offset to the FSYSx sysreg for UFS io coherency setting.
 
   dma-coherent: true
 
index bb373eb025a5f92b085d62b21354d94eaa002e65..00f87a558c7dd3b8af7392f87448ac8a00fbcd95 100644 (file)
@@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Xilinx SuperSpeed DWC3 USB SoC controller
 
 maintainers:
-  - Piyush Mehta <piyush.mehta@amd.com>
+  - Mubin Sayyed <mubin.sayyed@amd.com>
+  - Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
 
 properties:
   compatible:
index 6d4cfd943f5847ff43cbccd13e5f210a95448c1c..445183d9d6db1adaa1ab9d04cb4271eadbe22ffc 100644 (file)
@@ -16,8 +16,9 @@ description:
   USB 2.0 traffic.
 
 maintainers:
-  - Piyush Mehta <piyush.mehta@amd.com>
   - Michal Simek <michal.simek@amd.com>
+  - Mubin Sayyed <mubin.sayyed@amd.com>
+  - Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
 
 properties:
   compatible:
index 868dffe314bcba9123a4e99b9966de738b0ea8f3..a7f75fe366652bb2dcec6bf6e87c5879d31f1fce 100644 (file)
@@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Xilinx udc controller
 
 maintainers:
-  - Piyush Mehta <piyush.mehta@amd.com>
+  - Mubin Sayyed <mubin.sayyed@amd.com>
+  - Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
 
 properties:
   compatible:
index b14aed18065f43ce24e9217eefd455814c953efc..3dcc9ece272aad6842a6297c6d5bf2cca2c2acc3 100644 (file)
@@ -384,8 +384,6 @@ operations:
             - type
 
       dump:
-        pre: dpll-lock-dumpit
-        post: dpll-unlock-dumpit
         reply: *dev-attrs
 
     -
@@ -473,8 +471,6 @@ operations:
             - fractional-frequency-offset
 
       dump:
-        pre: dpll-lock-dumpit
-        post: dpll-unlock-dumpit
         request:
           attributes:
             - id
index e33ad2401ad70c8a678fec93ebfda3ca4909f9db..562f46b41274493c77176a1e563269fc9e4b2b85 100644 (file)
@@ -126,7 +126,7 @@ Users may also set the RoCE capability of the function using
 `devlink port function set roce` command.
 
 Users may also set the function as migratable using
-'devlink port function set migratable' command.
+`devlink port function set migratable` command.
 
 Users may also set the IPsec crypto capability of the function using
 `devlink port function set ipsec_crypto` command.
index e75a53593bb9606f1c0595d8f7227881ec932b9c..dceb49d56a91158232543e920c7ed23bed74106e 100644 (file)
@@ -136,8 +136,8 @@ struct_netpoll_info*                npinfo                  -
 possible_net_t                      nd_net                  -                   read_mostly         (dev_net)napi_busy_loop,tcp_v(4/6)_rcv,ip(v6)_rcv,ip(6)_input,ip(6)_input_finish
 void*                               ml_priv                                                         
 enum_netdev_ml_priv_type            ml_priv_type                                                    
-struct_pcpu_lstats__percpu*         lstats                                                          
-struct_pcpu_sw_netstats__percpu*    tstats                                                          
+struct_pcpu_lstats__percpu*         lstats                  read_mostly                             dev_lstats_add()
+struct_pcpu_sw_netstats__percpu*    tstats                  read_mostly                             dev_sw_netstats_tx_add()
 struct_pcpu_dstats__percpu*         dstats                                                          
 struct_garp_port*                   garp_port                                                       
 struct_mrp_port*                    mrp_port                                                        
index 97d7a5c8e01c02658c7f445ed92a2d1f7cc61d31..1c154cbd18487e385c8ae7a1e39d3b5f5ab086a2 100644 (file)
@@ -38,13 +38,13 @@ u32                           max_window              read_mostly         -
 u32                           mss_cache               read_mostly         read_mostly         tcp_rate_check_app_limited,tcp_current_mss,tcp_sync_mss,tcp_sndbuf_expand,tcp_tso_should_defer(tx);tcp_update_pacing_rate,tcp_clean_rtx_queue(rx)
 u32                           window_clamp            read_mostly         read_write          tcp_rcv_space_adjust,__tcp_select_window
 u32                           rcv_ssthresh            read_mostly         -                   __tcp_select_window
-u82                           scaling_ratio                                                   
+u8                            scaling_ratio           read_mostly         read_mostly         tcp_win_from_space
 struct                        tcp_rack                                                        
 u16                           advmss                  -                   read_mostly         tcp_rcv_space_adjust
 u8                            compressed_ack                                                  
 u8:2                          dup_ack_counter                                                 
 u8:1                          tlp_retrans                                                     
-u8:1                          tcp_usec_ts                                                     
+u8:1                          tcp_usec_ts             read_mostly         read_mostly
 u32                           chrono_start            read_write          -                   tcp_chrono_start/stop(tcp_write_xmit,tcp_cwnd_validate,tcp_send_syn_data)
 u32[3]                        chrono_stat             read_write          -                   tcp_chrono_start/stop(tcp_write_xmit,tcp_cwnd_validate,tcp_send_syn_data)
 u8:2                          chrono_type             read_write          -                   tcp_chrono_start/stop(tcp_write_xmit,tcp_cwnd_validate,tcp_send_syn_data)
index b9df61eb45013872ca82b463048494e041b3f127..03ace5f01b5c021e12adba23b83b8cb074c949ba 100644 (file)
@@ -109,7 +109,7 @@ class KernelFeat(Directive):
             else:
                 out_lines += line + "\n"
 
-        nodeList = self.nestedParse(out_lines, fname)
+        nodeList = self.nestedParse(out_lines, self.arguments[0])
         return nodeList
 
     def nestedParse(self, lines, fname):
index c4014b1d0ab45d419ccfcb191f62b9f32ee0717d..3dbb4db6e8586260b16f8ce226e5ea43158756a6 100644 (file)
@@ -4169,14 +4169,14 @@ F:      drivers/firmware/broadcom/tee_bnxt_fw.c
 F:     drivers/net/ethernet/broadcom/bnxt/
 F:     include/linux/firmware/broadcom/tee_bnxt_fw.h
 
-BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
-M:     Arend van Spriel <aspriel@gmail.com>
-M:     Franky Lin <franky.lin@broadcom.com>
-M:     Hante Meuleman <hante.meuleman@broadcom.com>
+BROADCOM BRCM80211 IEEE802.11 WIRELESS DRIVERS
+M:     Arend van Spriel <arend.vanspriel@broadcom.com>
 L:     linux-wireless@vger.kernel.org
+L:     brcm80211@lists.linux.dev
 L:     brcm80211-dev-list.pdl@broadcom.com
 S:     Supported
 F:     drivers/net/wireless/broadcom/brcm80211/
+F:     include/linux/platform_data/brcmfmac.h
 
 BROADCOM BRCMSTB GPIO DRIVER
 M:     Doug Berger <opendmb@gmail.com>
@@ -10801,11 +10801,11 @@ F:    drivers/gpio/gpio-tangier.h
 
 INTEL GVT-g DRIVERS (Intel GPU Virtualization)
 M:     Zhenyu Wang <zhenyuw@linux.intel.com>
-M:     Zhi Wang <zhi.a.wang@intel.com>
+M:     Zhi Wang <zhi.wang.linux@gmail.com>
 L:     intel-gvt-dev@lists.freedesktop.org
 L:     intel-gfx@lists.freedesktop.org
 S:     Supported
-W:     https://01.org/igvt-g
+W:     https://github.com/intel/gvt-linux/wiki
 T:     git https://github.com/intel/gvt-linux.git
 F:     drivers/gpu/drm/i915/gvt/
 
@@ -11127,7 +11127,6 @@ S:      Supported
 F:     drivers/net/wireless/intel/iwlegacy/
 
 INTEL WIRELESS WIFI LINK (iwlwifi)
-M:     Gregory Greenman <gregory.greenman@intel.com>
 M:     Miri Korenblit <miriam.rachel.korenblit@intel.com>
 L:     linux-wireless@vger.kernel.org
 S:     Supported
@@ -15325,7 +15324,7 @@ K:      \bmdo_
 NETWORKING [MPTCP]
 M:     Matthieu Baerts <matttbe@kernel.org>
 M:     Mat Martineau <martineau@kernel.org>
-R:     Geliang Tang <geliang.tang@linux.dev>
+R:     Geliang Tang <geliang@kernel.org>
 L:     netdev@vger.kernel.org
 L:     mptcp@lists.linux.dev
 S:     Maintained
@@ -16838,6 +16837,7 @@ F:      drivers/pci/controller/dwc/*designware*
 
 PCI DRIVER FOR TI DRA7XX/J721E
 M:     Vignesh Raghavendra <vigneshr@ti.com>
+R:     Siddharth Vadapalli <s-vadapalli@ti.com>
 L:     linux-omap@vger.kernel.org
 L:     linux-pci@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -17183,7 +17183,7 @@ R:      John Garry <john.g.garry@oracle.com>
 R:     Will Deacon <will@kernel.org>
 R:     James Clark <james.clark@arm.com>
 R:     Mike Leach <mike.leach@linaro.org>
-R:     Leo Yan <leo.yan@linaro.org>
+R:     Leo Yan <leo.yan@linux.dev>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     tools/build/feature/test-libopencsd.c
@@ -18432,7 +18432,7 @@ S:      Supported
 F:     drivers/infiniband/sw/rdmavt
 
 RDS - RELIABLE DATAGRAM SOCKETS
-M:     Santosh Shilimkar <santosh.shilimkar@oracle.com>
+M:     Allison Henderson <allison.henderson@oracle.com>
 L:     netdev@vger.kernel.org
 L:     linux-rdma@vger.kernel.org
 L:     rds-devel@oss.oracle.com (moderated for non-subscribers)
index a171eafce2a3b98d025cc071e54d3bf3c84f2446..7e0b2ad98905b91223d13ba03890d7839976ae0c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 8
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 9d96180797396bba26ace54f047f7a47bf82dd5f..a339223d9e052b35ea678d6a3e60faf6e5673671 100644 (file)
@@ -31,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key,
                                               bool branch)
 {
-       asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"   \n"
+       asm goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"            \n"
                 "1:                                                    \n"
                 "nop                                                   \n"
                 ".pushsection __jump_table, \"aw\"                     \n"
@@ -47,7 +47,7 @@ l_yes:
 static __always_inline bool arch_static_branch_jump(struct static_key *key,
                                                    bool branch)
 {
-       asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"   \n"
+       asm goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"            \n"
                 "1:                                                    \n"
                 "b %l[l_yes]                                           \n"
                 ".pushsection __jump_table, \"aw\"                     \n"
index e12d7d096fc034058bfaa094bf9b314a2a7a983d..e4eb54f6cd9fef41fecad56e25c4136e75455756 100644 (file)
@@ -11,7 +11,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                 WASM(nop) "\n\t"
                 ".pushsection __jump_table,  \"aw\"\n\t"
                 ".word 1b, %l[l_yes], %c0\n\t"
@@ -25,7 +25,7 @@ l_yes:
 
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                 WASM(b) " %l[l_yes]\n\t"
                 ".pushsection __jump_table,  \"aw\"\n\t"
                 ".word 1b, %l[l_yes], %c0\n\t"
index e96fb40b9cc32a64b5a0379e5ee42bd9e38f1aa5..07565b593ed681b0f1675f8ef7a934c1ae53dc51 100644 (file)
@@ -298,6 +298,8 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                goto done;
        }
        count_vm_vma_lock_event(VMA_LOCK_RETRY);
+       if (fault & VM_FAULT_MAJOR)
+               flags |= FAULT_FLAG_TRIED;
 
        /* Quick path to respond to signals */
        if (fault_signal_pending(fault, regs)) {
index 210bb43cff2c7d020fdf9dc1c8f2a99ca49415a0..d328f549b1a60a26bff884bccebe448fc0936f76 100644 (file)
@@ -229,7 +229,7 @@ alternative_has_cap_likely(const unsigned long cpucap)
        if (!cpucap_is_possible(cpucap))
                return false;
 
-       asm_volatile_goto(
+       asm goto(
        ALTERNATIVE_CB("b       %l[l_no]", %[cpucap], alt_cb_patch_nops)
        :
        : [cpucap] "i" (cpucap)
@@ -247,7 +247,7 @@ alternative_has_cap_unlikely(const unsigned long cpucap)
        if (!cpucap_is_possible(cpucap))
                return false;
 
-       asm_volatile_goto(
+       asm goto(
        ALTERNATIVE("nop", "b   %l[l_yes]", %[cpucap])
        :
        : [cpucap] "i" (cpucap)
index 21c824edf8ce4a6fa1c208b7a882df4b4e31eeb7..bd8d4ca81a48c9c3bfb012b1830eed185b7de679 100644 (file)
@@ -83,7 +83,7 @@ struct arm64_ftr_bits {
  * to full-0 denotes that this field has no override
  *
  * A @mask field set to full-0 with the corresponding @val field set
- * to full-1 denotes thath this field has an invalid override.
+ * to full-1 denotes that this field has an invalid override.
  */
 struct arm64_ftr_override {
        u64             val;
index 7c7493cb571f97bf98b0b4841aeb756d43990718..52f076afeb96006c42dfee6edefcf348048af96b 100644 (file)
@@ -61,6 +61,7 @@
 #define ARM_CPU_IMP_HISI               0x48
 #define ARM_CPU_IMP_APPLE              0x61
 #define ARM_CPU_IMP_AMPERE             0xC0
+#define ARM_CPU_IMP_MICROSOFT          0x6D
 
 #define ARM_CPU_PART_AEM_V8            0xD0F
 #define ARM_CPU_PART_FOUNDATION                0xD00
 
 #define AMPERE_CPU_PART_AMPERE1                0xAC3
 
+#define MICROSOFT_CPU_PART_AZURE_COBALT_100    0xD49 /* Based on r0p0 of ARM Neoverse N2 */
+
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
 #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
 #define MIDR_APPLE_M2_BLIZZARD_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX)
 #define MIDR_APPLE_M2_AVALANCHE_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX)
 #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1)
+#define MIDR_MICROSOFT_AZURE_COBALT_100 MIDR_CPU_MODEL(ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_AZURE_COBALT_100)
 
 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
 #define MIDR_FUJITSU_ERRATUM_010001            MIDR_FUJITSU_A64FX
index 50e5f25d3024ced8b3c107de352a69e65b6ab7f6..481d94416d696a87ddaf3754c275562540bbc3a1 100644 (file)
@@ -62,13 +62,13 @@ static inline void cpacr_restore(unsigned long cpacr)
  * When we defined the maximum SVE vector length we defined the ABI so
  * that the maximum vector length included all the reserved for future
  * expansion bits in ZCR rather than those just currently defined by
- * the architecture. While SME follows a similar pattern the fact that
- * it includes a square matrix means that any allocations that attempt
- * to cover the maximum potential vector length (such as happen with
- * the regset used for ptrace) end up being extremely large. Define
- * the much lower actual limit for use in such situations.
+ * the architecture.  Using this length to allocate worst size buffers
+ * results in excessively large allocations, and this effect is even
+ * more pronounced for SME due to ZA.  Define more suitable VLs for
+ * these situations.
  */
-#define SME_VQ_MAX     16
+#define ARCH_SVE_VQ_MAX ((ZCR_ELx_LEN_MASK >> ZCR_ELx_LEN_SHIFT) + 1)
+#define SME_VQ_MAX     ((SMCR_ELx_LEN_MASK >> SMCR_ELx_LEN_SHIFT) + 1)
 
 struct task_struct;
 
index 48ddc0f45d2283f2c5ba0de62f5d3231999a91f3..b360c4c2b5e792ef276443ca550b535e7050cb35 100644 (file)
 
 #define JUMP_LABEL_NOP_SIZE            AARCH64_INSN_SIZE
 
+/*
+ * Prefer the constraint "S" to support PIC with GCC. Clang before 19 does not
+ * support "S" on a symbol with a constant offset, so we use "i" as a fallback.
+ */
 static __always_inline bool arch_static_branch(struct static_key * const key,
                                               const bool branch)
 {
-       asm_volatile_goto(
+       asm goto(
                "1:     nop                                     \n\t"
                 "      .pushsection    __jump_table, \"aw\"    \n\t"
                 "      .align          3                       \n\t"
                 "      .long           1b - ., %l[l_yes] - .   \n\t"
-                "      .quad           %c0 - .                 \n\t"
+                "      .quad           (%[key] - .) + %[bit0]  \n\t"
                 "      .popsection                             \n\t"
-                :  :  "i"(&((char *)key)[branch]) :  : l_yes);
+                :  :  [key]"Si"(key), [bit0]"i"(branch) :  : l_yes);
 
        return false;
 l_yes:
@@ -35,14 +39,14 @@ l_yes:
 static __always_inline bool arch_static_branch_jump(struct static_key * const key,
                                                    const bool branch)
 {
-       asm_volatile_goto(
+       asm goto(
                "1:     b               %l[l_yes]               \n\t"
                 "      .pushsection    __jump_table, \"aw\"    \n\t"
                 "      .align          3                       \n\t"
                 "      .long           1b - ., %l[l_yes] - .   \n\t"
-                "      .quad           %c0 - .                 \n\t"
+                "      .quad           (%[key] - .) + %[bit0]  \n\t"
                 "      .popsection                             \n\t"
-                :  :  "i"(&((char *)key)[branch]) :  : l_yes);
+                :  :  [key]"Si"(key), [bit0]"i"(branch) :  : l_yes);
 
        return false;
 l_yes:
index 967c7c7a4e7db3db7e3d05a7637e8e7d13e0d273..76b8dd37092ad2a9dd6e59a92d1c1fab887589da 100644 (file)
@@ -374,6 +374,7 @@ static const struct midr_range erratum_1463225[] = {
 static const struct midr_range trbe_overwrite_fill_mode_cpus[] = {
 #ifdef CONFIG_ARM64_ERRATUM_2139208
        MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
+       MIDR_ALL_VERSIONS(MIDR_MICROSOFT_AZURE_COBALT_100),
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_2119858
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
@@ -387,6 +388,7 @@ static const struct midr_range trbe_overwrite_fill_mode_cpus[] = {
 static const struct midr_range tsb_flush_fail_cpus[] = {
 #ifdef CONFIG_ARM64_ERRATUM_2067961
        MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
+       MIDR_ALL_VERSIONS(MIDR_MICROSOFT_AZURE_COBALT_100),
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_2054223
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
@@ -399,6 +401,7 @@ static const struct midr_range tsb_flush_fail_cpus[] = {
 static struct midr_range trbe_write_out_of_range_cpus[] = {
 #ifdef CONFIG_ARM64_ERRATUM_2253138
        MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
+       MIDR_ALL_VERSIONS(MIDR_MICROSOFT_AZURE_COBALT_100),
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_2224489
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
index a5dc6f764195847251dc25c196304cbef44d8850..25ceaee6b025da204857af8faeadae2fa83f128c 100644 (file)
@@ -1635,7 +1635,7 @@ void fpsimd_preserve_current_state(void)
 void fpsimd_signal_preserve_current_state(void)
 {
        fpsimd_preserve_current_state();
-       if (test_thread_flag(TIF_SVE))
+       if (current->thread.fp_type == FP_STATE_SVE)
                sve_to_fpsimd(current);
 }
 
index dc6cf0e37194e428519d7d58524ad0f624f4bebb..e3bef38fc2e2d36b85a9a4069729e276f9368846 100644 (file)
@@ -1500,7 +1500,8 @@ static const struct user_regset aarch64_regsets[] = {
 #ifdef CONFIG_ARM64_SVE
        [REGSET_SVE] = { /* Scalable Vector Extension */
                .core_note_type = NT_ARM_SVE,
-               .n = DIV_ROUND_UP(SVE_PT_SIZE(SVE_VQ_MAX, SVE_PT_REGS_SVE),
+               .n = DIV_ROUND_UP(SVE_PT_SIZE(ARCH_SVE_VQ_MAX,
+                                             SVE_PT_REGS_SVE),
                                  SVE_VQ_BYTES),
                .size = SVE_VQ_BYTES,
                .align = SVE_VQ_BYTES,
index 0e8beb3349ea2a1aae6340f879f78dd568e04f51..425b1bc17a3f6dc3237e81fabcb35d774f1aa9d1 100644 (file)
@@ -242,7 +242,7 @@ static int preserve_sve_context(struct sve_context __user *ctx)
                vl = task_get_sme_vl(current);
                vq = sve_vq_from_vl(vl);
                flags |= SVE_SIG_FLAG_SM;
-       } else if (test_thread_flag(TIF_SVE)) {
+       } else if (current->thread.fp_type == FP_STATE_SVE) {
                vq = sve_vq_from_vl(vl);
        }
 
@@ -878,7 +878,7 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
        if (system_supports_sve() || system_supports_sme()) {
                unsigned int vq = 0;
 
-               if (add_all || test_thread_flag(TIF_SVE) ||
+               if (add_all || current->thread.fp_type == FP_STATE_SVE ||
                    thread_sm_enabled(&current->thread)) {
                        int vl = max(sve_max_vl(), sme_max_vl());
 
index 6c3c8ca73e7fda8bb29792218bb11d031e7527ff..27ca89b628a02499d18505953ad1cee73ccf7f88 100644 (file)
@@ -3,7 +3,6 @@
 # KVM configuration
 #
 
-source "virt/lib/Kconfig"
 source "virt/kvm/Kconfig"
 
 menuconfig VIRTUALIZATION
index c651df904fe3eb940e07785aac1ac76079743666..ab9d05fcf98b23b992343d6a11a1daf9de806b3a 100644 (file)
@@ -1419,7 +1419,6 @@ kvm_pte_t *kvm_pgtable_stage2_create_unlinked(struct kvm_pgtable *pgt,
                                 level + 1);
        if (ret) {
                kvm_pgtable_stage2_free_unlinked(mm_ops, pgtable, level);
-               mm_ops->put_page(pgtable);
                return ERR_PTR(ret);
        }
 
@@ -1502,7 +1501,6 @@ static int stage2_split_walker(const struct kvm_pgtable_visit_ctx *ctx,
 
        if (!stage2_try_break_pte(ctx, mmu)) {
                kvm_pgtable_stage2_free_unlinked(mm_ops, childp, level);
-               mm_ops->put_page(childp);
                return -EAGAIN;
        }
 
index 8350fb8fee0b998ccf27dca4b7bf2e858846ccd3..b7be96a5359737d41576af46eee1f68852632846 100644 (file)
@@ -101,6 +101,17 @@ void __init kvm_hyp_reserve(void)
                 hyp_mem_base);
 }
 
+static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm)
+{
+       if (host_kvm->arch.pkvm.handle) {
+               WARN_ON(kvm_call_hyp_nvhe(__pkvm_teardown_vm,
+                                         host_kvm->arch.pkvm.handle));
+       }
+
+       host_kvm->arch.pkvm.handle = 0;
+       free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc);
+}
+
 /*
  * Allocates and donates memory for hypervisor VM structs at EL2.
  *
@@ -181,7 +192,7 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
        return 0;
 
 destroy_vm:
-       pkvm_destroy_hyp_vm(host_kvm);
+       __pkvm_destroy_hyp_vm(host_kvm);
        return ret;
 free_vm:
        free_pages_exact(hyp_vm, hyp_vm_sz);
@@ -194,23 +205,19 @@ int pkvm_create_hyp_vm(struct kvm *host_kvm)
 {
        int ret = 0;
 
-       mutex_lock(&host_kvm->lock);
+       mutex_lock(&host_kvm->arch.config_lock);
        if (!host_kvm->arch.pkvm.handle)
                ret = __pkvm_create_hyp_vm(host_kvm);
-       mutex_unlock(&host_kvm->lock);
+       mutex_unlock(&host_kvm->arch.config_lock);
 
        return ret;
 }
 
 void pkvm_destroy_hyp_vm(struct kvm *host_kvm)
 {
-       if (host_kvm->arch.pkvm.handle) {
-               WARN_ON(kvm_call_hyp_nvhe(__pkvm_teardown_vm,
-                                         host_kvm->arch.pkvm.handle));
-       }
-
-       host_kvm->arch.pkvm.handle = 0;
-       free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc);
+       mutex_lock(&host_kvm->arch.config_lock);
+       __pkvm_destroy_hyp_vm(host_kvm);
+       mutex_unlock(&host_kvm->arch.config_lock);
 }
 
 int pkvm_init_host_vm(struct kvm *host_kvm)
index 98a3f4b168bd2687f3e4828aa681d29e0c13b97e..ef2e37a10a0feb9af3543481cffddd75c5b3a8ef 100644 (file)
@@ -12,7 +12,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key,
                                               bool branch)
 {
-       asm_volatile_goto(
+       asm goto(
                "1:     nop32                                   \n"
                "       .pushsection    __jump_table, \"aw\"    \n"
                "       .align          2                       \n"
@@ -29,7 +29,7 @@ label:
 static __always_inline bool arch_static_branch_jump(struct static_key *key,
                                                    bool branch)
 {
-       asm_volatile_goto(
+       asm goto(
                "1:     bsr32           %l[label]               \n"
                "       .pushsection    __jump_table, \"aw\"    \n"
                "       .align          2                       \n"
index 10959e6c3583255264aef0ea7de6e6477a003418..929f68926b3432e52a6d7b84a92d402a5d8bc11a 100644 (file)
@@ -12,6 +12,7 @@ config LOONGARCH
        select ARCH_DISABLE_KASAN_INLINE
        select ARCH_ENABLE_MEMORY_HOTPLUG
        select ARCH_ENABLE_MEMORY_HOTREMOVE
+       select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
        select ARCH_HAS_ACPI_TABLE_UPGRADE      if ACPI
        select ARCH_HAS_CPU_FINALIZE_INIT
        select ARCH_HAS_FORTIFY_SOURCE
@@ -99,6 +100,7 @@ config LOONGARCH
        select HAVE_ARCH_KFENCE
        select HAVE_ARCH_KGDB if PERF_EVENTS
        select HAVE_ARCH_MMAP_RND_BITS if MMU
+       select HAVE_ARCH_SECCOMP
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
@@ -632,23 +634,6 @@ config RANDOMIZE_BASE_MAX_OFFSET
 
          This is limited by the size of the lower address memory, 256MB.
 
-config SECCOMP
-       bool "Enable seccomp to safely compute untrusted bytecode"
-       depends on PROC_FS
-       default y
-       help
-         This kernel feature is useful for number crunching applications
-         that may need to compute untrusted bytecode during their
-         execution. By using pipes or other transports made available to
-         the process as file descriptors supporting the read/write
-         syscalls, it's possible to isolate those applications in
-         their own address space using seccomp. Once seccomp is
-         enabled via /proc/<pid>/seccomp, it cannot be disabled
-         and the task is only allowed to execute a few safe syscalls
-         defined by each seccomp mode.
-
-         If unsure, say Y. Only embedded should say N here.
-
 endmenu
 
 config ARCH_SELECT_MEMORY_MODEL
@@ -667,10 +652,6 @@ config ARCH_SPARSEMEM_ENABLE
          or have huge holes in the physical address space for other reasons.
          See <file:Documentation/mm/numa.rst> for more.
 
-config ARCH_ENABLE_THP_MIGRATION
-       def_bool y
-       depends on TRANSPARENT_HUGEPAGE
-
 config ARCH_MEMORY_PROBE
        def_bool y
        depends on MEMORY_HOTPLUG
index 8de6c4b83a61a8088903abc67ddc50beb35233d5..49e29b29996f0f4473c5d628c936c7528630ad52 100644 (file)
@@ -32,8 +32,10 @@ static inline bool acpi_has_cpu_in_madt(void)
        return true;
 }
 
+#define MAX_CORE_PIC 256
+
 extern struct list_head acpi_wakeup_device_list;
-extern struct acpi_madt_core_pic acpi_core_pic[NR_CPUS];
+extern struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC];
 
 extern int __init parse_acpi_topology(void);
 
index 3cea299a5ef58313a305f7d5a086ae9a32e8aa95..29acfe3de3faae797beca198e58f9e5a5e570bbc 100644 (file)
@@ -22,7 +22,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
 {
-       asm_volatile_goto(
+       asm goto(
                "1:     nop                     \n\t"
                JUMP_TABLE_ENTRY
                :  :  "i"(&((char *)key)[branch]) :  : l_yes);
@@ -35,7 +35,7 @@ l_yes:
 
 static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
 {
-       asm_volatile_goto(
+       asm goto(
                "1:     b       %l[l_yes]       \n\t"
                JUMP_TABLE_ENTRY
                :  :  "i"(&((char *)key)[branch]) :  : l_yes);
index b6b097bbf8668a400105dd408c696e4135c824d8..5cf59c617126b7d00f65b3310ef39ea7bfb98e96 100644 (file)
@@ -29,11 +29,9 @@ int disabled_cpus;
 
 u64 acpi_saved_sp;
 
-#define MAX_CORE_PIC 256
-
 #define PREFIX                 "ACPI: "
 
-struct acpi_madt_core_pic acpi_core_pic[NR_CPUS];
+struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC];
 
 void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size)
 {
index cc3e81fe0186f4f0fa8de9cedfc75138583ce23f..c608adc9984581d0419594a8eb87ae18a3e9ec63 100644 (file)
@@ -44,6 +44,9 @@ void *kasan_mem_to_shadow(const void *addr)
                unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff;
                unsigned long offset = 0;
 
+               if (maddr >= FIXADDR_START)
+                       return (void *)(kasan_early_shadow_page);
+
                maddr &= XRANGE_SHADOW_MASK;
                switch (xrange) {
                case XKPRANGE_CC_SEG:
index c74c9921304f2273fea31278cfafce7b143a75ea..f597cd08a96be0a19084884bd175678a6a83d6ab 100644 (file)
@@ -2,6 +2,7 @@
 # Objects to go into the VDSO.
 
 KASAN_SANITIZE := n
+UBSAN_SANITIZE := n
 KCOV_INSTRUMENT := n
 
 # Include the generic Makefile to check the built vdso.
index 4044eaf989ac7dad0f2094c5d4cfab05ac9fb5c3..0921ddda11a4b353c1c4d754417d3de4d003c12f 100644 (file)
@@ -241,7 +241,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
        "       .set    pop"
        : "=&r" (sum), "=&r" (tmp)
        : "r" (saddr), "r" (daddr),
-         "0" (htonl(len)), "r" (htonl(proto)), "r" (sum));
+         "0" (htonl(len)), "r" (htonl(proto)), "r" (sum)
+       : "memory");
 
        return csum_fold(sum);
 }
index 081be98c71ef48c698f4aa6ba14945239a666a9d..ff5d388502d4ab56ec28d71ad4126d542bb65977 100644 (file)
@@ -39,7 +39,7 @@ extern void jump_label_apply_nops(struct module *mod);
 
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\t" B_INSN " 2f\n\t"
+       asm goto("1:\t" B_INSN " 2f\n\t"
                "2:\t.insn\n\t"
                ".pushsection __jump_table,  \"aw\"\n\t"
                WORD_INSN " 1b, %l[l_yes], %0\n\t"
@@ -53,7 +53,7 @@ l_yes:
 
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\t" J_INSN " %l[l_yes]\n\t"
+       asm goto("1:\t" J_INSN " %l[l_yes]\n\t"
                ".pushsection __jump_table,  \"aw\"\n\t"
                WORD_INSN " 1b, %l[l_yes], %0\n\t"
                ".popsection\n\t"
index daf3cf244ea972c9a8bf134a09fa081931645425..d14d0e37ad02ddf10b42cfed590c65f97f8de424 100644 (file)
@@ -60,6 +60,7 @@ static inline void instruction_pointer_set(struct pt_regs *regs,
                                            unsigned long val)
 {
        regs->cp0_epc = val;
+       regs->cp0_cause &= ~CAUSEF_BD;
 }
 
 /* Query offset/name of register from its name/offset */
@@ -154,6 +155,8 @@ static inline long regs_return_value(struct pt_regs *regs)
 }
 
 #define instruction_pointer(regs) ((regs)->cp0_epc)
+extern unsigned long exception_ip(struct pt_regs *regs);
+#define exception_ip(regs) exception_ip(regs)
 #define profile_pc(regs) instruction_pointer(regs)
 
 extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
index d9df543f7e2c4cd17b29522840154f1e323cacb0..59288c13b581b89ccb46214c7be02126a017dab2 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/seccomp.h>
 #include <linux/ftrace.h>
 
+#include <asm/branch.h>
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
 #include <asm/cpu-info.h>
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
+unsigned long exception_ip(struct pt_regs *regs)
+{
+       return exception_epc(regs);
+}
+EXPORT_SYMBOL(exception_ip);
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
index 94428798b6aa63e8d4b0878cc7555826cf080e47..317ebc5edc9fe99950f4efe55d989db453f46d0d 100644 (file)
@@ -12,7 +12,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                 "nop\n\t"
                 ".pushsection __jump_table,  \"aw\"\n\t"
                 ".align %1\n\t"
@@ -29,7 +29,7 @@ l_yes:
 
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                 "b,n %l[l_yes]\n\t"
                 ".pushsection __jump_table,  \"aw\"\n\t"
                 ".align %1\n\t"
index 93ce3ec253877d38da5e3f9c3ac76205354d3496..2f2a86ed2280aac66df0535d7938cf4a673446f7 100644 (file)
@@ -17,7 +17,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                 "nop # arch_static_branch\n\t"
                 ".pushsection __jump_table,  \"aw\"\n\t"
                 ".long 1b - ., %l[l_yes] - .\n\t"
@@ -32,7 +32,7 @@ l_yes:
 
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                 "b %l[l_yes] # arch_static_branch_jump\n\t"
                 ".pushsection __jump_table,  \"aw\"\n\t"
                 ".long 1b - ., %l[l_yes] - .\n\t"
index f1f9890f50d3ef84dfd62b5d66db68315f0698b6..de10437fd20652ee63a6d214638bded13cdbc6c3 100644 (file)
@@ -74,7 +74,7 @@ __pu_failed:                                                  \
 /* -mprefixed can generate offsets beyond range, fall back hack */
 #ifdef CONFIG_PPC_KERNEL_PREFIXED
 #define __put_user_asm_goto(x, addr, label, op)                        \
-       asm_volatile_goto(                                      \
+       asm goto(                                       \
                "1:     " op " %0,0(%1) # put_user\n"           \
                EX_TABLE(1b, %l2)                               \
                :                                               \
@@ -83,7 +83,7 @@ __pu_failed:                                                  \
                : label)
 #else
 #define __put_user_asm_goto(x, addr, label, op)                        \
-       asm_volatile_goto(                                      \
+       asm goto(                                       \
                "1:     " op "%U1%X1 %0,%1      # put_user\n"   \
                EX_TABLE(1b, %l2)                               \
                :                                               \
@@ -97,7 +97,7 @@ __pu_failed:                                                  \
        __put_user_asm_goto(x, ptr, label, "std")
 #else /* __powerpc64__ */
 #define __put_user_asm2_goto(x, addr, label)                   \
-       asm_volatile_goto(                                      \
+       asm goto(                                       \
                "1:     stw%X1 %0, %1\n"                        \
                "2:     stw%X1 %L0, %L1\n"                      \
                EX_TABLE(1b, %l2)                               \
@@ -146,7 +146,7 @@ do {                                                                \
 /* -mprefixed can generate offsets beyond range, fall back hack */
 #ifdef CONFIG_PPC_KERNEL_PREFIXED
 #define __get_user_asm_goto(x, addr, label, op)                        \
-       asm_volatile_goto(                                      \
+       asm_goto_output(                                        \
                "1:     "op" %0,0(%1)   # get_user\n"           \
                EX_TABLE(1b, %l2)                               \
                : "=r" (x)                                      \
@@ -155,7 +155,7 @@ do {                                                                \
                : label)
 #else
 #define __get_user_asm_goto(x, addr, label, op)                        \
-       asm_volatile_goto(                                      \
+       asm_goto_output(                                        \
                "1:     "op"%U1%X1 %0, %1       # get_user\n"   \
                EX_TABLE(1b, %l2)                               \
                : "=r" (x)                                      \
@@ -169,7 +169,7 @@ do {                                                                \
        __get_user_asm_goto(x, addr, label, "ld")
 #else /* __powerpc64__ */
 #define __get_user_asm2_goto(x, addr, label)                   \
-       asm_volatile_goto(                                      \
+       asm_goto_output(                                        \
                "1:     lwz%X1 %0, %1\n"                        \
                "2:     lwz%X1 %L0, %L1\n"                      \
                EX_TABLE(1b, %l2)                               \
index 938e66829eae65cc52d170f7753ee0685cdaa4e3..d5c48d1b0a31ea533281934e414320bbf77368d2 100644 (file)
@@ -230,7 +230,7 @@ again:
         * This allows interrupts to be unmasked without hard disabling, and
         * also without new hard interrupts coming in ahead of pending ones.
         */
-       asm_volatile_goto(
+       asm goto(
 "1:                                    \n"
 "              lbz     9,%0(13)        \n"
 "              cmpwi   9,0             \n"
index c20236a0725b9e27a31d28b580db1bd1ad2c945a..85b2c443823e8ab8ce55aa5b32953eabbc5e1108 100644 (file)
@@ -20,7 +20,7 @@
 static __always_inline unsigned int __arch_hweight32(unsigned int w)
 {
 #ifdef CONFIG_RISCV_ISA_ZBB
-       asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+       asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
                                      RISCV_ISA_EXT_ZBB, 1)
                          : : : : legacy);
 
@@ -51,7 +51,7 @@ static inline unsigned int __arch_hweight8(unsigned int w)
 static __always_inline unsigned long __arch_hweight64(__u64 w)
 {
 # ifdef CONFIG_RISCV_ISA_ZBB
-       asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+       asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
                                      RISCV_ISA_EXT_ZBB, 1)
                          : : : : legacy);
 
index 9ffc355370248aed22dbe690ba1cde8e682a3588..329d8244a9b3fd516104808db5a959acfb469b22 100644 (file)
@@ -39,7 +39,7 @@ static __always_inline unsigned long variable__ffs(unsigned long word)
 {
        int num;
 
-       asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+       asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
                                      RISCV_ISA_EXT_ZBB, 1)
                          : : : : legacy);
 
@@ -95,7 +95,7 @@ static __always_inline unsigned long variable__fls(unsigned long word)
 {
        int num;
 
-       asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+       asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
                                      RISCV_ISA_EXT_ZBB, 1)
                          : : : : legacy);
 
@@ -154,7 +154,7 @@ static __always_inline int variable_ffs(int x)
        if (!x)
                return 0;
 
-       asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+       asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
                                      RISCV_ISA_EXT_ZBB, 1)
                          : : : : legacy);
 
@@ -209,7 +209,7 @@ static __always_inline int variable_fls(unsigned int x)
        if (!x)
                return 0;
 
-       asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+       asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
                                      RISCV_ISA_EXT_ZBB, 1)
                          : : : : legacy);
 
index a5b60b54b101c3ba1e550b3e16e7096a6bfc8357..88e6f1499e889951b2871fec052330b3c92f2eb7 100644 (file)
@@ -53,7 +53,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
            IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
                unsigned long fold_temp;
 
-               asm_volatile_goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0,
+               asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0,
                                              RISCV_ISA_EXT_ZBB, 1)
                    :
                    :
index 5a626ed2c47a8915b3848df2e7f4a7ea0601bd71..0bd11862b7607b9ffebf8460ea6cc00cc1e4ff62 100644 (file)
@@ -80,7 +80,7 @@ riscv_has_extension_likely(const unsigned long ext)
                           "ext must be < RISCV_ISA_EXT_MAX");
 
        if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
-               asm_volatile_goto(
+               asm goto(
                ALTERNATIVE("j  %l[l_no]", "nop", 0, %[ext], 1)
                :
                : [ext] "i" (ext)
@@ -103,7 +103,7 @@ riscv_has_extension_unlikely(const unsigned long ext)
                           "ext must be < RISCV_ISA_EXT_MAX");
 
        if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
-               asm_volatile_goto(
+               asm goto(
                ALTERNATIVE("nop", "j   %l[l_yes]", 0, %[ext], 1)
                :
                : [ext] "i" (ext)
index 4c5b0e929890fadcebb3caace0afe97dfa46d8bf..20f9c3ba2341412812ba003caf86f546c162bd34 100644 (file)
@@ -11,6 +11,9 @@ static inline void arch_clear_hugepage_flags(struct page *page)
 }
 #define arch_clear_hugepage_flags arch_clear_hugepage_flags
 
+bool arch_hugetlb_migration_supported(struct hstate *h);
+#define arch_hugetlb_migration_supported arch_hugetlb_migration_supported
+
 #ifdef CONFIG_RISCV_ISA_SVNAPOT
 #define __HAVE_ARCH_HUGE_PTE_CLEAR
 void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
index 14a5ea8d8ef0f4a2f4477fb65778e4f8ea449e2a..4a35d787c0191475b3a5d8dc7452e448541dc8e9 100644 (file)
@@ -17,7 +17,7 @@
 static __always_inline bool arch_static_branch(struct static_key * const key,
                                               const bool branch)
 {
-       asm_volatile_goto(
+       asm goto(
                "       .align          2                       \n\t"
                "       .option push                            \n\t"
                "       .option norelax                         \n\t"
@@ -39,7 +39,7 @@ label:
 static __always_inline bool arch_static_branch_jump(struct static_key * const key,
                                                    const bool branch)
 {
-       asm_volatile_goto(
+       asm goto(
                "       .align          2                       \n\t"
                "       .option push                            \n\t"
                "       .option norelax                         \n\t"
index f7e8ef2418b99fc98362a1a977f8038f7592fbac..b1495a7e06ce693b4fc698ee4d62549bd0614700 100644 (file)
@@ -21,4 +21,9 @@ static inline bool on_thread_stack(void)
        return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
 }
 
+
+#ifdef CONFIG_VMAP_STACK
+DECLARE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack);
+#endif /* CONFIG_VMAP_STACK */
+
 #endif /* _ASM_RISCV_STACKTRACE_H */
index 1eb5682b2af6065c9019e398df729f5b97a573c6..50b63b5c15bd8b19dac37176ef98c3489c837e05 100644 (file)
@@ -16,7 +16,7 @@ static void tlb_flush(struct mmu_gather *tlb);
 static inline void tlb_flush(struct mmu_gather *tlb)
 {
 #ifdef CONFIG_MMU
-       if (tlb->fullmm || tlb->need_flush_all)
+       if (tlb->fullmm || tlb->need_flush_all || tlb->freed_tables)
                flush_tlb_mm(tlb->mm);
        else
                flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end,
index 928f096dca21b4e6cbafc009595cd34bb9917109..4112cc8d1d69f9fbde77a524820a5de1e7931acf 100644 (file)
@@ -75,6 +75,7 @@ static inline void flush_tlb_kernel_range(unsigned long start,
 
 #define flush_tlb_mm(mm) flush_tlb_all()
 #define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all()
+#define local_flush_tlb_kernel_range(start, end) flush_tlb_all()
 #endif /* !CONFIG_SMP || !CONFIG_MMU */
 
 #endif /* _ASM_RISCV_TLBFLUSH_H */
index d6b7a5b958742c443bce93e067434128c1cff7e4..7499e88a947c086c5f569e98a899f50d098a8335 100644 (file)
@@ -139,6 +139,33 @@ enum KVM_RISCV_ISA_EXT_ID {
        KVM_RISCV_ISA_EXT_ZIHPM,
        KVM_RISCV_ISA_EXT_SMSTATEEN,
        KVM_RISCV_ISA_EXT_ZICOND,
+       KVM_RISCV_ISA_EXT_ZBC,
+       KVM_RISCV_ISA_EXT_ZBKB,
+       KVM_RISCV_ISA_EXT_ZBKC,
+       KVM_RISCV_ISA_EXT_ZBKX,
+       KVM_RISCV_ISA_EXT_ZKND,
+       KVM_RISCV_ISA_EXT_ZKNE,
+       KVM_RISCV_ISA_EXT_ZKNH,
+       KVM_RISCV_ISA_EXT_ZKR,
+       KVM_RISCV_ISA_EXT_ZKSED,
+       KVM_RISCV_ISA_EXT_ZKSH,
+       KVM_RISCV_ISA_EXT_ZKT,
+       KVM_RISCV_ISA_EXT_ZVBB,
+       KVM_RISCV_ISA_EXT_ZVBC,
+       KVM_RISCV_ISA_EXT_ZVKB,
+       KVM_RISCV_ISA_EXT_ZVKG,
+       KVM_RISCV_ISA_EXT_ZVKNED,
+       KVM_RISCV_ISA_EXT_ZVKNHA,
+       KVM_RISCV_ISA_EXT_ZVKNHB,
+       KVM_RISCV_ISA_EXT_ZVKSED,
+       KVM_RISCV_ISA_EXT_ZVKSH,
+       KVM_RISCV_ISA_EXT_ZVKT,
+       KVM_RISCV_ISA_EXT_ZFH,
+       KVM_RISCV_ISA_EXT_ZFHMIN,
+       KVM_RISCV_ISA_EXT_ZIHINTNTL,
+       KVM_RISCV_ISA_EXT_ZVFH,
+       KVM_RISCV_ISA_EXT_ZVFHMIN,
+       KVM_RISCV_ISA_EXT_ZFA,
        KVM_RISCV_ISA_EXT_MAX,
 };
 
index 8e114f5930cec6148b98f7f81abd72a798caf8e8..0d6225fd3194e14ed71ac9afc716b2e81168e9a5 100644 (file)
@@ -41,7 +41,7 @@ static int __init parse_no_stealacc(char *arg)
 
 early_param("no-steal-acc", parse_no_stealacc);
 
-DEFINE_PER_CPU(struct sbi_sta_struct, steal_time) __aligned(64);
+static DEFINE_PER_CPU(struct sbi_sta_struct, steal_time) __aligned(64);
 
 static bool __init has_pv_steal_clock(void)
 {
@@ -91,8 +91,8 @@ static int pv_time_cpu_down_prepare(unsigned int cpu)
 static u64 pv_time_steal_clock(int cpu)
 {
        struct sbi_sta_struct *st = per_cpu_ptr(&steal_time, cpu);
-       u32 sequence;
-       u64 steal;
+       __le32 sequence;
+       __le64 steal;
 
        /*
         * Check the sequence field before and after reading the steal
index fc34557f5356e27902a2f83c27eb37f1237c9b95..5f7355e960084b4a4a17ea294e92352f7a70da60 100644 (file)
@@ -42,15 +42,42 @@ static const unsigned long kvm_isa_ext_arr[] = {
        KVM_ISA_EXT_ARR(SVPBMT),
        KVM_ISA_EXT_ARR(ZBA),
        KVM_ISA_EXT_ARR(ZBB),
+       KVM_ISA_EXT_ARR(ZBC),
+       KVM_ISA_EXT_ARR(ZBKB),
+       KVM_ISA_EXT_ARR(ZBKC),
+       KVM_ISA_EXT_ARR(ZBKX),
        KVM_ISA_EXT_ARR(ZBS),
+       KVM_ISA_EXT_ARR(ZFA),
+       KVM_ISA_EXT_ARR(ZFH),
+       KVM_ISA_EXT_ARR(ZFHMIN),
        KVM_ISA_EXT_ARR(ZICBOM),
        KVM_ISA_EXT_ARR(ZICBOZ),
        KVM_ISA_EXT_ARR(ZICNTR),
        KVM_ISA_EXT_ARR(ZICOND),
        KVM_ISA_EXT_ARR(ZICSR),
        KVM_ISA_EXT_ARR(ZIFENCEI),
+       KVM_ISA_EXT_ARR(ZIHINTNTL),
        KVM_ISA_EXT_ARR(ZIHINTPAUSE),
        KVM_ISA_EXT_ARR(ZIHPM),
+       KVM_ISA_EXT_ARR(ZKND),
+       KVM_ISA_EXT_ARR(ZKNE),
+       KVM_ISA_EXT_ARR(ZKNH),
+       KVM_ISA_EXT_ARR(ZKR),
+       KVM_ISA_EXT_ARR(ZKSED),
+       KVM_ISA_EXT_ARR(ZKSH),
+       KVM_ISA_EXT_ARR(ZKT),
+       KVM_ISA_EXT_ARR(ZVBB),
+       KVM_ISA_EXT_ARR(ZVBC),
+       KVM_ISA_EXT_ARR(ZVFH),
+       KVM_ISA_EXT_ARR(ZVFHMIN),
+       KVM_ISA_EXT_ARR(ZVKB),
+       KVM_ISA_EXT_ARR(ZVKG),
+       KVM_ISA_EXT_ARR(ZVKNED),
+       KVM_ISA_EXT_ARR(ZVKNHA),
+       KVM_ISA_EXT_ARR(ZVKNHB),
+       KVM_ISA_EXT_ARR(ZVKSED),
+       KVM_ISA_EXT_ARR(ZVKSH),
+       KVM_ISA_EXT_ARR(ZVKT),
 };
 
 static unsigned long kvm_riscv_vcpu_base2isa_ext(unsigned long base_ext)
@@ -92,13 +119,40 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
        case KVM_RISCV_ISA_EXT_SVNAPOT:
        case KVM_RISCV_ISA_EXT_ZBA:
        case KVM_RISCV_ISA_EXT_ZBB:
+       case KVM_RISCV_ISA_EXT_ZBC:
+       case KVM_RISCV_ISA_EXT_ZBKB:
+       case KVM_RISCV_ISA_EXT_ZBKC:
+       case KVM_RISCV_ISA_EXT_ZBKX:
        case KVM_RISCV_ISA_EXT_ZBS:
+       case KVM_RISCV_ISA_EXT_ZFA:
+       case KVM_RISCV_ISA_EXT_ZFH:
+       case KVM_RISCV_ISA_EXT_ZFHMIN:
        case KVM_RISCV_ISA_EXT_ZICNTR:
        case KVM_RISCV_ISA_EXT_ZICOND:
        case KVM_RISCV_ISA_EXT_ZICSR:
        case KVM_RISCV_ISA_EXT_ZIFENCEI:
+       case KVM_RISCV_ISA_EXT_ZIHINTNTL:
        case KVM_RISCV_ISA_EXT_ZIHINTPAUSE:
        case KVM_RISCV_ISA_EXT_ZIHPM:
+       case KVM_RISCV_ISA_EXT_ZKND:
+       case KVM_RISCV_ISA_EXT_ZKNE:
+       case KVM_RISCV_ISA_EXT_ZKNH:
+       case KVM_RISCV_ISA_EXT_ZKR:
+       case KVM_RISCV_ISA_EXT_ZKSED:
+       case KVM_RISCV_ISA_EXT_ZKSH:
+       case KVM_RISCV_ISA_EXT_ZKT:
+       case KVM_RISCV_ISA_EXT_ZVBB:
+       case KVM_RISCV_ISA_EXT_ZVBC:
+       case KVM_RISCV_ISA_EXT_ZVFH:
+       case KVM_RISCV_ISA_EXT_ZVFHMIN:
+       case KVM_RISCV_ISA_EXT_ZVKB:
+       case KVM_RISCV_ISA_EXT_ZVKG:
+       case KVM_RISCV_ISA_EXT_ZVKNED:
+       case KVM_RISCV_ISA_EXT_ZVKNHA:
+       case KVM_RISCV_ISA_EXT_ZVKNHB:
+       case KVM_RISCV_ISA_EXT_ZVKSED:
+       case KVM_RISCV_ISA_EXT_ZVKSH:
+       case KVM_RISCV_ISA_EXT_ZVKT:
                return false;
        /* Extensions which can be disabled using Smstateen */
        case KVM_RISCV_ISA_EXT_SSAIA:
index 01f09fe8c3b020968be3f623097c9a48ab958087..d8cf9ca28c616e9d4073465a71dcc7479be3d35a 100644 (file)
@@ -26,8 +26,12 @@ void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu)
 {
        gpa_t shmem = vcpu->arch.sta.shmem;
        u64 last_steal = vcpu->arch.sta.last_steal;
-       u32 *sequence_ptr, sequence;
-       u64 *steal_ptr, steal;
+       __le32 __user *sequence_ptr;
+       __le64 __user *steal_ptr;
+       __le32 sequence_le;
+       __le64 steal_le;
+       u32 sequence;
+       u64 steal;
        unsigned long hva;
        gfn_t gfn;
 
@@ -47,22 +51,22 @@ void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu)
                return;
        }
 
-       sequence_ptr = (u32 *)(hva + offset_in_page(shmem) +
+       sequence_ptr = (__le32 __user *)(hva + offset_in_page(shmem) +
                               offsetof(struct sbi_sta_struct, sequence));
-       steal_ptr = (u64 *)(hva + offset_in_page(shmem) +
+       steal_ptr = (__le64 __user *)(hva + offset_in_page(shmem) +
                            offsetof(struct sbi_sta_struct, steal));
 
-       if (WARN_ON(get_user(sequence, sequence_ptr)))
+       if (WARN_ON(get_user(sequence_le, sequence_ptr)))
                return;
 
-       sequence = le32_to_cpu(sequence);
+       sequence = le32_to_cpu(sequence_le);
        sequence += 1;
 
        if (WARN_ON(put_user(cpu_to_le32(sequence), sequence_ptr)))
                return;
 
-       if (!WARN_ON(get_user(steal, steal_ptr))) {
-               steal = le64_to_cpu(steal);
+       if (!WARN_ON(get_user(steal_le, steal_ptr))) {
+               steal = le64_to_cpu(steal_le);
                vcpu->arch.sta.last_steal = READ_ONCE(current->sched_info.run_delay);
                steal += vcpu->arch.sta.last_steal - last_steal;
                WARN_ON(put_user(cpu_to_le64(steal), steal_ptr));
index af3df5274ccbae0118488080040f45881a3e025a..74af3ab520b6d433836930937dd90ffa2e672339 100644 (file)
@@ -53,7 +53,7 @@ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
                 * support, so nop when Zbb is available and jump when Zbb is
                 * not available.
                 */
-               asm_volatile_goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0,
+               asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0,
                                              RISCV_ISA_EXT_ZBB, 1)
                                  :
                                  :
@@ -170,7 +170,7 @@ do_csum_with_alignment(const unsigned char *buff, int len)
                 * support, so nop when Zbb is available and jump when Zbb is
                 * not available.
                 */
-               asm_volatile_goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0,
+               asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0,
                                              RISCV_ISA_EXT_ZBB, 1)
                                  :
                                  :
@@ -178,7 +178,7 @@ do_csum_with_alignment(const unsigned char *buff, int len)
                                  : no_zbb);
 
 #ifdef CONFIG_32BIT
-               asm_volatile_goto(".option push                 \n\
+               asm_goto_output(".option push                   \n\
                .option arch,+zbb                               \n\
                        rori    %[fold_temp], %[csum], 16       \n\
                        andi    %[offset], %[offset], 1         \n\
@@ -193,7 +193,7 @@ do_csum_with_alignment(const unsigned char *buff, int len)
 
                return (unsigned short)csum;
 #else /* !CONFIG_32BIT */
-               asm_volatile_goto(".option push                 \n\
+               asm_goto_output(".option push                   \n\
                .option arch,+zbb                               \n\
                        rori    %[fold_temp], %[csum], 32       \n\
                        add     %[csum], %[fold_temp], %[csum]  \n\
@@ -257,7 +257,7 @@ do_csum_no_alignment(const unsigned char *buff, int len)
                 * support, so nop when Zbb is available and jump when Zbb is
                 * not available.
                 */
-               asm_volatile_goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0,
+               asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0,
                                              RISCV_ISA_EXT_ZBB, 1)
                                  :
                                  :
index 431596c0e20e04e1ad5a2422fa989f27cdfdc7c4..29c7606414d276d1c3639e2a80e10037ea899cfc 100644 (file)
@@ -125,6 +125,26 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
        return pte;
 }
 
+unsigned long hugetlb_mask_last_page(struct hstate *h)
+{
+       unsigned long hp_size = huge_page_size(h);
+
+       switch (hp_size) {
+#ifndef __PAGETABLE_PMD_FOLDED
+       case PUD_SIZE:
+               return P4D_SIZE - PUD_SIZE;
+#endif
+       case PMD_SIZE:
+               return PUD_SIZE - PMD_SIZE;
+       case napot_cont_size(NAPOT_CONT64KB_ORDER):
+               return PMD_SIZE - napot_cont_size(NAPOT_CONT64KB_ORDER);
+       default:
+               break;
+       }
+
+       return 0UL;
+}
+
 static pte_t get_clear_contig(struct mm_struct *mm,
                              unsigned long addr,
                              pte_t *ptep,
@@ -177,13 +197,36 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
        return entry;
 }
 
+static void clear_flush(struct mm_struct *mm,
+                       unsigned long addr,
+                       pte_t *ptep,
+                       unsigned long pgsize,
+                       unsigned long ncontig)
+{
+       struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
+       unsigned long i, saddr = addr;
+
+       for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
+               ptep_get_and_clear(mm, addr, ptep);
+
+       flush_tlb_range(&vma, saddr, addr);
+}
+
+/*
+ * When dealing with NAPOT mappings, the privileged specification indicates that
+ * "if an update needs to be made, the OS generally should first mark all of the
+ * PTEs invalid, then issue SFENCE.VMA instruction(s) covering all 4 KiB regions
+ * within the range, [...] then update the PTE(s), as described in Section
+ * 4.2.1.". That's the equivalent of the Break-Before-Make approach used by
+ * arm64.
+ */
 void set_huge_pte_at(struct mm_struct *mm,
                     unsigned long addr,
                     pte_t *ptep,
                     pte_t pte,
                     unsigned long sz)
 {
-       unsigned long hugepage_shift;
+       unsigned long hugepage_shift, pgsize;
        int i, pte_num;
 
        if (sz >= PGDIR_SIZE)
@@ -198,7 +241,22 @@ void set_huge_pte_at(struct mm_struct *mm,
                hugepage_shift = PAGE_SHIFT;
 
        pte_num = sz >> hugepage_shift;
-       for (i = 0; i < pte_num; i++, ptep++, addr += (1 << hugepage_shift))
+       pgsize = 1 << hugepage_shift;
+
+       if (!pte_present(pte)) {
+               for (i = 0; i < pte_num; i++, ptep++, addr += pgsize)
+                       set_ptes(mm, addr, ptep, pte, 1);
+               return;
+       }
+
+       if (!pte_napot(pte)) {
+               set_ptes(mm, addr, ptep, pte, 1);
+               return;
+       }
+
+       clear_flush(mm, addr, ptep, pgsize, pte_num);
+
+       for (i = 0; i < pte_num; i++, ptep++, addr += pgsize)
                set_pte_at(mm, addr, ptep, pte);
 }
 
@@ -306,7 +364,7 @@ void huge_pte_clear(struct mm_struct *mm,
                pte_clear(mm, addr, ptep);
 }
 
-static __init bool is_napot_size(unsigned long size)
+static bool is_napot_size(unsigned long size)
 {
        unsigned long order;
 
@@ -334,7 +392,7 @@ arch_initcall(napot_hugetlbpages_init);
 
 #else
 
-static __init bool is_napot_size(unsigned long size)
+static bool is_napot_size(unsigned long size)
 {
        return false;
 }
@@ -351,7 +409,7 @@ int pmd_huge(pmd_t pmd)
        return pmd_leaf(pmd);
 }
 
-bool __init arch_hugetlb_valid_size(unsigned long size)
+static bool __hugetlb_valid_size(unsigned long size)
 {
        if (size == HPAGE_SIZE)
                return true;
@@ -363,6 +421,16 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
                return false;
 }
 
+bool __init arch_hugetlb_valid_size(unsigned long size)
+{
+       return __hugetlb_valid_size(size);
+}
+
+bool arch_hugetlb_migration_supported(struct hstate *h)
+{
+       return __hugetlb_valid_size(huge_page_size(h));
+}
+
 #ifdef CONFIG_CONTIG_ALLOC
 static __init int gigantic_pages_init(void)
 {
index 32cad6a65ccd23431d63097a0906ca5b8de485f8..fa34cf55037bd37ad0b8d3bb3b67f6f91d243f58 100644 (file)
@@ -1385,6 +1385,10 @@ void __init misc_mem_init(void)
        early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT);
        arch_numa_init();
        sparse_init();
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+       /* The entire VMEMMAP region has been populated. Flush TLB for this region */
+       local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END);
+#endif
        zone_sizes_init();
        arch_reserve_crashkernel();
        memblock_dump_all();
index 8d12b26f5ac37b659687981c2046f3d5b590753c..893566e004b73fcf9a8dbc94f766e59cd00f1bb1 100644 (file)
@@ -66,9 +66,10 @@ static inline void local_flush_tlb_range_asid(unsigned long start,
                local_flush_tlb_range_threshold_asid(start, size, stride, asid);
 }
 
+/* Flush a range of kernel pages without broadcasting */
 void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
-       local_flush_tlb_range_asid(start, end, PAGE_SIZE, FLUSH_TLB_NO_ASID);
+       local_flush_tlb_range_asid(start, end - start, PAGE_SIZE, FLUSH_TLB_NO_ASID);
 }
 
 static void __ipi_flush_tlb_all(void *info)
@@ -233,4 +234,5 @@ void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
 {
        __flush_tlb_range(&batch->cpumask, FLUSH_TLB_NO_ASID, 0,
                          FLUSH_TLB_MAX_SIZE, PAGE_SIZE);
+       cpumask_clear(&batch->cpumask);
 }
index 895f774bbcc55353cc7a3d302b009796a799446f..bf78cf381dfcdac92a170b754328acd16846eb2e 100644 (file)
@@ -25,7 +25,7 @@
  */
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("0:   brcl 0,%l[label]\n"
+       asm goto("0:    brcl 0,%l[label]\n"
                          ".pushsection __jump_table,\"aw\"\n"
                          ".balign      8\n"
                          ".long        0b-.,%l[label]-.\n"
@@ -39,7 +39,7 @@ label:
 
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("0:   brcl 15,%l[label]\n"
+       asm goto("0:    brcl 15,%l[label]\n"
                          ".pushsection __jump_table,\"aw\"\n"
                          ".balign      8\n"
                          ".long        0b-.,%l[label]-.\n"
index 621a17fd1a1bb52fd7875a134a1acac25f004209..f875a404a0a02555d5875128fafedcfe54d5b4d6 100644 (file)
@@ -676,8 +676,12 @@ static int handle_pqap(struct kvm_vcpu *vcpu)
        if (vcpu->kvm->arch.crypto.pqap_hook) {
                pqap_hook = *vcpu->kvm->arch.crypto.pqap_hook;
                ret = pqap_hook(vcpu);
-               if (!ret && vcpu->run->s.regs.gprs[1] & 0x00ff0000)
-                       kvm_s390_set_psw_cc(vcpu, 3);
+               if (!ret) {
+                       if (vcpu->run->s.regs.gprs[1] & 0x00ff0000)
+                               kvm_s390_set_psw_cc(vcpu, 3);
+                       else
+                               kvm_s390_set_psw_cc(vcpu, 0);
+               }
                up_read(&vcpu->kvm->arch.crypto.pqap_hook_rwsem);
                return ret;
        }
index fef42e2a80a2ae5bc47eae89f2b4e38293a2586b..3af3bd20ac7b8f075e08b85b34f7e257f4687eeb 100644 (file)
@@ -1235,7 +1235,6 @@ static int acquire_gmap_shadow(struct kvm_vcpu *vcpu,
        gmap = gmap_shadow(vcpu->arch.gmap, asce, edat);
        if (IS_ERR(gmap))
                return PTR_ERR(gmap);
-       gmap->private = vcpu->kvm;
        vcpu->kvm->stat.gmap_shadow_create++;
        WRITE_ONCE(vsie_page->gmap, gmap);
        return 0;
index 6f96b5a71c6383d07eb447cb80df70214bdd1910..8da39deb56ca4952a6f8e436d153ec6f54292932 100644 (file)
@@ -1691,6 +1691,7 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce,
                return ERR_PTR(-ENOMEM);
        new->mm = parent->mm;
        new->parent = gmap_get(parent);
+       new->private = parent->private;
        new->orig_asce = asce;
        new->edat_level = edat_level;
        new->initialized = false;
index 94eb529dcb77623caf637387e694d8e5ddc049a8..2718cbea826a7d13aefacd26fee3719b69856746 100644 (file)
@@ -10,7 +10,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                 "nop\n\t"
                 "nop\n\t"
                 ".pushsection __jump_table,  \"aw\"\n\t"
@@ -26,7 +26,7 @@ l_yes:
 
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                 "b %l[l_yes]\n\t"
                 "nop\n\t"
                 ".pushsection __jump_table,  \"aw\"\n\t"
index 4b6d1b526bc1217e2e89d4670f9c4385e68dacc7..66fe06db872f05bb775f0089a4f134f77563efe4 100644 (file)
@@ -75,7 +75,7 @@ extern void setup_clear_cpu_cap(unsigned int bit);
  */
 static __always_inline bool _static_cpu_has(u16 bit)
 {
-       asm_volatile_goto("1: jmp 6f\n"
+       asm goto("1: jmp 6f\n"
                 "2:\n"
                 ".skip -(((5f-4f) - (2b-1b)) > 0) * "
                         "((5f-4f) - (2b-1b)),0x90\n"
index b9224cf2ee4d6fcb234be76e072d37fa1cc7ad53..2a7279d80460a8adf0218a954646d9d8343ddf3e 100644 (file)
@@ -379,7 +379,7 @@ config X86_CMOV
 config X86_MINIMUM_CPU_FAMILY
        int
        default "64" if X86_64
-       default "6" if X86_32 && (MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MEFFICEON || MATOM || MCRUSOE || MCORE2 || MK7 || MK8)
+       default "6" if X86_32 && (MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MEFFICEON || MATOM || MCORE2 || MK7 || MK8)
        default "5" if X86_32 && X86_CMPXCHG64
        default "4"
 
index b2771710ed989cc805e6310bd88a1743350a9dc5..a1bbedd989e42ed5f9e433f556613613094ae74d 100644 (file)
@@ -106,8 +106,7 @@ extra_header_fields:
        .word   0                               # MinorSubsystemVersion
        .long   0                               # Win32VersionValue
 
-       .long   setup_size + ZO__end + pecompat_vsize
-                                               # SizeOfImage
+       .long   setup_size + ZO__end            # SizeOfImage
 
        .long   salign                          # SizeOfHeaders
        .long   0                               # CheckSum
@@ -143,7 +142,7 @@ section_table:
        .ascii  ".setup"
        .byte   0
        .byte   0
-       .long   setup_size - salign             # VirtualSize
+       .long   pecompat_fstart - salign        # VirtualSize
        .long   salign                          # VirtualAddress
        .long   pecompat_fstart - salign        # SizeOfRawData
        .long   salign                          # PointerToRawData
@@ -156,8 +155,8 @@ section_table:
 #ifdef CONFIG_EFI_MIXED
        .asciz  ".compat"
 
-       .long   8                               # VirtualSize
-       .long   setup_size + ZO__end            # VirtualAddress
+       .long   pecompat_fsize                  # VirtualSize
+       .long   pecompat_fstart                 # VirtualAddress
        .long   pecompat_fsize                  # SizeOfRawData
        .long   pecompat_fstart                 # PointerToRawData
 
@@ -172,17 +171,16 @@ section_table:
         * modes this image supports.
         */
        .pushsection ".pecompat", "a", @progbits
-       .balign falign
-       .set    pecompat_vsize, salign
+       .balign salign
        .globl  pecompat_fstart
 pecompat_fstart:
        .byte   0x1                             # Version
        .byte   8                               # Size
        .word   IMAGE_FILE_MACHINE_I386         # PE machine type
        .long   setup_size + ZO_efi32_pe_entry  # Entrypoint
+       .byte   0x0                             # Sentinel
        .popsection
 #else
-       .set    pecompat_vsize, 0
        .set    pecompat_fstart, setup_size
 #endif
        .ascii  ".text"
index 83bb7efad8ae7139ca66f850d7bb21b4859bd3e0..3a2d1360abb016902495f5879632335d883b8c03 100644 (file)
@@ -24,6 +24,9 @@ SECTIONS
        .text           : { *(.text .text.*) }
        .text32         : { *(.text32) }
 
+       .pecompat       : { *(.pecompat) }
+       PROVIDE(pecompat_fsize = setup_size - pecompat_fstart);
+
        . = ALIGN(16);
        .rodata         : { *(.rodata*) }
 
@@ -36,9 +39,6 @@ SECTIONS
        . = ALIGN(16);
        .data           : { *(.data*) }
 
-       .pecompat       : { *(.pecompat) }
-       PROVIDE(pecompat_fsize = setup_size - pecompat_fstart);
-
        .signature      : {
                setup_sig = .;
                LONG(0x5a5aaa55)
index 6ae2d16a7613b714cb58283dafa600db5829ba6f..76c310b19b11d898db11cf498d7c82449bbf7dc2 100644 (file)
@@ -10,13 +10,14 @@ enum cc_vendor {
        CC_VENDOR_INTEL,
 };
 
-extern enum cc_vendor cc_vendor;
-
 #ifdef CONFIG_ARCH_HAS_CC_PLATFORM
+extern enum cc_vendor cc_vendor;
 void cc_set_mask(u64 mask);
 u64 cc_mkenc(u64 val);
 u64 cc_mkdec(u64 val);
 #else
+#define cc_vendor (CC_VENDOR_NONE)
+
 static inline u64 cc_mkenc(u64 val)
 {
        return val;
index a26bebbdff87ed20c45bdb98dcc4a8873f5c30f5..a1273698fc430b41951c241b6b76dfa9b7887692 100644 (file)
@@ -168,7 +168,7 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);
  */
 static __always_inline bool _static_cpu_has(u16 bit)
 {
-       asm_volatile_goto(
+       asm goto(
                ALTERNATIVE_TERNARY("jmp 6f", %P[feature], "", "jmp %l[t_no]")
                ".pushsection .altinstr_aux,\"ax\"\n"
                "6:\n"
index 071572e23d3a06783e3a1f63e11bb47e99af9daa..cbbef32517f0049a3df51842162032ff1946e901 100644 (file)
@@ -24,7 +24,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
-       asm_volatile_goto("1:"
+       asm goto("1:"
                "jmp %l[l_yes] # objtool NOPs this \n\t"
                JUMP_TABLE_ENTRY
                : :  "i" (key), "i" (2 | branch) : : l_yes);
@@ -38,7 +38,7 @@ l_yes:
 
 static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
 {
-       asm_volatile_goto("1:"
+       asm goto("1:"
                ".byte " __stringify(BYTES_NOP5) "\n\t"
                JUMP_TABLE_ENTRY
                : :  "i" (key), "i" (branch) : : l_yes);
@@ -52,7 +52,7 @@ l_yes:
 
 static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
 {
-       asm_volatile_goto("1:"
+       asm goto("1:"
                "jmp %l[l_yes]\n\t"
                JUMP_TABLE_ENTRY
                : :  "i" (key), "i" (branch) : : l_yes);
index b5b2d0fde5796894534f0cb98f96d3076b6bf27d..d271ba20a0b214104a1f11832a1007f5bb35190e 100644 (file)
@@ -1145,6 +1145,8 @@ struct kvm_hv {
        unsigned int synic_auto_eoi_used;
 
        struct kvm_hv_syndbg hv_syndbg;
+
+       bool xsaves_xsavec_checked;
 };
 #endif
 
index 4b081e0d3306b79cca3dc222bb7406cde371d517..363266cbcadaf29e5bdeba4b0bfd5ab0ccb7355f 100644 (file)
@@ -13,7 +13,7 @@
 #define __GEN_RMWcc(fullop, _var, cc, clobbers, ...)                   \
 ({                                                                     \
        bool c = false;                                                 \
-       asm_volatile_goto (fullop "; j" #cc " %l[cc_label]"             \
+       asm goto (fullop "; j" #cc " %l[cc_label]"              \
                        : : [var] "m" (_var), ## __VA_ARGS__            \
                        : clobbers : cc_label);                         \
        if (0) {                                                        \
index d6cd9344f6c78e5555486e5d9f231fd27de9da6a..48f8dd47cf6882ac9e3920d6e7105c0eff430528 100644 (file)
@@ -205,7 +205,7 @@ static inline void clwb(volatile void *__p)
 #ifdef CONFIG_X86_USER_SHADOW_STACK
 static inline int write_user_shstk_64(u64 __user *addr, u64 val)
 {
-       asm_volatile_goto("1: wrussq %[val], (%[addr])\n"
+       asm goto("1: wrussq %[val], (%[addr])\n"
                          _ASM_EXTABLE(1b, %l[fail])
                          :: [addr] "r" (addr), [val] "r" (val)
                          :: fail);
index 5c367c1290c355fb3849800a38c88c3553175903..237dc8cdd12b9482f38f8543b85dbde88fb98d65 100644 (file)
@@ -133,7 +133,7 @@ extern int __get_user_bad(void);
 
 #ifdef CONFIG_X86_32
 #define __put_user_goto_u64(x, addr, label)                    \
-       asm_volatile_goto("\n"                                  \
+       asm goto("\n"                                   \
                     "1:        movl %%eax,0(%1)\n"             \
                     "2:        movl %%edx,4(%1)\n"             \
                     _ASM_EXTABLE_UA(1b, %l2)                   \
@@ -295,7 +295,7 @@ do {                                                                        \
 } while (0)
 
 #define __get_user_asm(x, addr, itype, ltype, label)                   \
-       asm_volatile_goto("\n"                                          \
+       asm_goto_output("\n"                                            \
                     "1:        mov"itype" %[umem],%[output]\n"         \
                     _ASM_EXTABLE_UA(1b, %l2)                           \
                     : [output] ltype(x)                                \
@@ -375,7 +375,7 @@ do {                                                                        \
        __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
        __typeof__(*(_ptr)) __old = *_old;                              \
        __typeof__(*(_ptr)) __new = (_new);                             \
-       asm_volatile_goto("\n"                                          \
+       asm_goto_output("\n"                                            \
                     "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
                     _ASM_EXTABLE_UA(1b, %l[label])                     \
                     : CC_OUT(z) (success),                             \
@@ -394,7 +394,7 @@ do {                                                                        \
        __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
        __typeof__(*(_ptr)) __old = *_old;                              \
        __typeof__(*(_ptr)) __new = (_new);                             \
-       asm_volatile_goto("\n"                                          \
+       asm_goto_output("\n"                                            \
                     "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"             \
                     _ASM_EXTABLE_UA(1b, %l[label])                     \
                     : CC_OUT(z) (success),                             \
@@ -477,7 +477,7 @@ struct __large_struct { unsigned long buf[100]; };
  * aliasing issues.
  */
 #define __put_user_goto(x, addr, itype, ltype, label)                  \
-       asm_volatile_goto("\n"                                          \
+       asm goto("\n"                                                   \
                "1:     mov"itype" %0,%1\n"                             \
                _ASM_EXTABLE_UA(1b, %l2)                                \
                : : ltype(x), "m" (__m(addr))                           \
index 558076dbde5bfca582139f8de63bd9ffa1050d6f..247f2225aa9f36f0a0fef0a22ed921b4748a7de5 100644 (file)
@@ -274,12 +274,13 @@ static int __restore_fpregs_from_user(void __user *buf, u64 ufeatures,
  * Attempt to restore the FPU registers directly from user memory.
  * Pagefaults are handled and any errors returned are fatal.
  */
-static bool restore_fpregs_from_user(void __user *buf, u64 xrestore,
-                                    bool fx_only, unsigned int size)
+static bool restore_fpregs_from_user(void __user *buf, u64 xrestore, bool fx_only)
 {
        struct fpu *fpu = &current->thread.fpu;
        int ret;
 
+       /* Restore enabled features only. */
+       xrestore &= fpu->fpstate->user_xfeatures;
 retry:
        fpregs_lock();
        /* Ensure that XFD is up to date */
@@ -309,7 +310,7 @@ retry:
                if (ret != X86_TRAP_PF)
                        return false;
 
-               if (!fault_in_readable(buf, size))
+               if (!fault_in_readable(buf, fpu->fpstate->user_size))
                        goto retry;
                return false;
        }
@@ -339,7 +340,6 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,
        struct user_i387_ia32_struct env;
        bool success, fx_only = false;
        union fpregs_state *fpregs;
-       unsigned int state_size;
        u64 user_xfeatures = 0;
 
        if (use_xsave()) {
@@ -349,17 +349,14 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,
                        return false;
 
                fx_only = !fx_sw_user.magic1;
-               state_size = fx_sw_user.xstate_size;
                user_xfeatures = fx_sw_user.xfeatures;
        } else {
                user_xfeatures = XFEATURE_MASK_FPSSE;
-               state_size = fpu->fpstate->user_size;
        }
 
        if (likely(!ia32_fxstate)) {
                /* Restore the FPU registers directly from user memory. */
-               return restore_fpregs_from_user(buf_fx, user_xfeatures, fx_only,
-                                               state_size);
+               return restore_fpregs_from_user(buf_fx, user_xfeatures, fx_only);
        }
 
        /*
index dfe9945b9becee7f6d0ca89d00fd3c1eb4e496c5..428ee74002e1eac63d0e269510f536ba2644c3f7 100644 (file)
@@ -434,7 +434,8 @@ static void __init sev_map_percpu_data(void)
 {
        int cpu;
 
-       if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
+       if (cc_vendor != CC_VENDOR_AMD ||
+           !cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
                return;
 
        for_each_possible_cpu(cpu) {
index 4943f6b2bbee491651bdacf288e4cdbda2e49dec..8a47f8541eab7098c991837c2b4e03c4822c445a 100644 (file)
@@ -1322,6 +1322,56 @@ static bool hv_check_msr_access(struct kvm_vcpu_hv *hv_vcpu, u32 msr)
        return false;
 }
 
+#define KVM_HV_WIN2016_GUEST_ID 0x1040a00003839
+#define KVM_HV_WIN2016_GUEST_ID_MASK (~GENMASK_ULL(23, 16)) /* mask out the service version */
+
+/*
+ * Hyper-V enabled Windows Server 2016 SMP VMs fail to boot in !XSAVES && XSAVEC
+ * configuration.
+ * Such configuration can result from, for example, AMD Erratum 1386 workaround.
+ *
+ * Print a notice so users aren't left wondering what's suddenly gone wrong.
+ */
+static void __kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu)
+{
+       struct kvm *kvm = vcpu->kvm;
+       struct kvm_hv *hv = to_kvm_hv(kvm);
+
+       /* Check again under the hv_lock.  */
+       if (hv->xsaves_xsavec_checked)
+               return;
+
+       if ((hv->hv_guest_os_id & KVM_HV_WIN2016_GUEST_ID_MASK) !=
+           KVM_HV_WIN2016_GUEST_ID)
+               return;
+
+       hv->xsaves_xsavec_checked = true;
+
+       /* UP configurations aren't affected */
+       if (atomic_read(&kvm->online_vcpus) < 2)
+               return;
+
+       if (guest_cpuid_has(vcpu, X86_FEATURE_XSAVES) ||
+           !guest_cpuid_has(vcpu, X86_FEATURE_XSAVEC))
+               return;
+
+       pr_notice_ratelimited("Booting SMP Windows KVM VM with !XSAVES && XSAVEC. "
+                             "If it fails to boot try disabling XSAVEC in the VM config.\n");
+}
+
+void kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu)
+{
+       struct kvm_hv *hv = to_kvm_hv(vcpu->kvm);
+
+       if (!vcpu->arch.hyperv_enabled ||
+           hv->xsaves_xsavec_checked)
+               return;
+
+       mutex_lock(&hv->hv_lock);
+       __kvm_hv_xsaves_xsavec_maybe_warn(vcpu);
+       mutex_unlock(&hv->hv_lock);
+}
+
 static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data,
                             bool host)
 {
index 1dc0b6604526a1c629b3709d54c674f1ae1ce080..923e64903da9afeeff80f76062c45bd5ab076717 100644 (file)
@@ -182,6 +182,8 @@ void kvm_hv_setup_tsc_page(struct kvm *kvm,
                           struct pvclock_vcpu_time_info *hv_clock);
 void kvm_hv_request_tsc_page_update(struct kvm *kvm);
 
+void kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu);
+
 void kvm_hv_init_vm(struct kvm *kvm);
 void kvm_hv_destroy_vm(struct kvm *kvm);
 int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu);
@@ -267,6 +269,7 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu);
 static inline void kvm_hv_setup_tsc_page(struct kvm *kvm,
                                         struct pvclock_vcpu_time_info *hv_clock) {}
 static inline void kvm_hv_request_tsc_page_update(struct kvm *kvm) {}
+static inline void kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu) {}
 static inline void kvm_hv_init_vm(struct kvm *kvm) {}
 static inline void kvm_hv_destroy_vm(struct kvm *kvm) {}
 static inline int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu)
index 36c8af87a707ac0556fb1e50157e70c6305df798..4e725854c63a10c8645fa3b875a7a718020e96fe 100644 (file)
@@ -8,7 +8,7 @@
 
 #define svm_asm(insn, clobber...)                              \
 do {                                                           \
-       asm_volatile_goto("1: " __stringify(insn) "\n\t"        \
+       asm goto("1: " __stringify(insn) "\n\t" \
                          _ASM_EXTABLE(1b, %l[fault])           \
                          ::: clobber : fault);                 \
        return;                                                 \
@@ -18,7 +18,7 @@ fault:                                                                \
 
 #define svm_asm1(insn, op1, clobber...)                                \
 do {                                                           \
-       asm_volatile_goto("1: "  __stringify(insn) " %0\n\t"    \
+       asm goto("1: "  __stringify(insn) " %0\n\t"     \
                          _ASM_EXTABLE(1b, %l[fault])           \
                          :: op1 : clobber : fault);            \
        return;                                                 \
@@ -28,7 +28,7 @@ fault:                                                                \
 
 #define svm_asm2(insn, op1, op2, clobber...)                           \
 do {                                                                   \
-       asm_volatile_goto("1: "  __stringify(insn) " %1, %0\n\t"        \
+       asm goto("1: "  __stringify(insn) " %1, %0\n\t" \
                          _ASM_EXTABLE(1b, %l[fault])                   \
                          :: op1, op2 : clobber : fault);               \
        return;                                                         \
index a6216c8747291f4c8aeed534117fad1f3808acb8..315c7c2ba89b13437fe4c3cbb93d92f75bd8f3f1 100644 (file)
@@ -71,7 +71,7 @@ static int fixed_pmc_events[] = {
 static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
 {
        struct kvm_pmc *pmc;
-       u8 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl;
+       u64 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl;
        int i;
 
        pmu->fixed_ctr_ctrl = data;
index e262bc2ba4e569983a94c3db5c13e1f0dabd9951..1111d9d089038b2f17b372891a235222b74f87bf 100644 (file)
@@ -738,7 +738,7 @@ static int vmx_set_guest_uret_msr(struct vcpu_vmx *vmx,
  */
 static int kvm_cpu_vmxoff(void)
 {
-       asm_volatile_goto("1: vmxoff\n\t"
+       asm goto("1: vmxoff\n\t"
                          _ASM_EXTABLE(1b, %l[fault])
                          ::: "cc", "memory" : fault);
 
@@ -2784,7 +2784,7 @@ static int kvm_cpu_vmxon(u64 vmxon_pointer)
 
        cr4_set_bits(X86_CR4_VMXE);
 
-       asm_volatile_goto("1: vmxon %[vmxon_pointer]\n\t"
+       asm goto("1: vmxon %[vmxon_pointer]\n\t"
                          _ASM_EXTABLE(1b, %l[fault])
                          : : [vmxon_pointer] "m"(vmxon_pointer)
                          : : fault);
index f41ce3c24123a93e08a996d4daa8e033077caf6d..8060e5fc6dbd83e145f6c08fca370e4a42d9861b 100644 (file)
@@ -94,7 +94,7 @@ static __always_inline unsigned long __vmcs_readl(unsigned long field)
 
 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
 
-       asm_volatile_goto("1: vmread %[field], %[output]\n\t"
+       asm_goto_output("1: vmread %[field], %[output]\n\t"
                          "jna %l[do_fail]\n\t"
 
                          _ASM_EXTABLE(1b, %l[do_exception])
@@ -188,7 +188,7 @@ static __always_inline unsigned long vmcs_readl(unsigned long field)
 
 #define vmx_asm1(insn, op1, error_args...)                             \
 do {                                                                   \
-       asm_volatile_goto("1: " __stringify(insn) " %0\n\t"             \
+       asm goto("1: " __stringify(insn) " %0\n\t"                      \
                          ".byte 0x2e\n\t" /* branch not taken hint */  \
                          "jna %l[error]\n\t"                           \
                          _ASM_EXTABLE(1b, %l[fault])                   \
@@ -205,7 +205,7 @@ fault:                                                                      \
 
 #define vmx_asm2(insn, op1, op2, error_args...)                                \
 do {                                                                   \
-       asm_volatile_goto("1: "  __stringify(insn) " %1, %0\n\t"        \
+       asm goto("1: "  __stringify(insn) " %1, %0\n\t"                 \
                          ".byte 0x2e\n\t" /* branch not taken hint */  \
                          "jna %l[error]\n\t"                           \
                          _ASM_EXTABLE(1b, %l[fault])                   \
index 363b1c08020578b090b53d74482d9c8912629ec9..48a61d283406f36a4f5230f508376a1fb951d58b 100644 (file)
@@ -1704,22 +1704,17 @@ static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
        struct kvm_msr_entry msr;
        int r;
 
+       /* Unconditionally clear the output for simplicity */
+       msr.data = 0;
        msr.index = index;
        r = kvm_get_msr_feature(&msr);
 
-       if (r == KVM_MSR_RET_INVALID) {
-               /* Unconditionally clear the output for simplicity */
-               *data = 0;
-               if (kvm_msr_ignored_check(index, 0, false))
-                       r = 0;
-       }
-
-       if (r)
-               return r;
+       if (r == KVM_MSR_RET_INVALID && kvm_msr_ignored_check(index, 0, false))
+               r = 0;
 
        *data = msr.data;
 
-       return 0;
+       return r;
 }
 
 static bool __kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
@@ -1782,6 +1777,10 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        if ((efer ^ old_efer) & KVM_MMU_EFER_ROLE_BITS)
                kvm_mmu_reset_context(vcpu);
 
+       if (!static_cpu_has(X86_FEATURE_XSAVES) &&
+           (efer & EFER_SVME))
+               kvm_hv_xsaves_xsavec_maybe_warn(vcpu);
+
        return 0;
 }
 
@@ -2507,7 +2506,7 @@ static u64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns)
 }
 
 #ifdef CONFIG_X86_64
-static inline int gtod_is_based_on_tsc(int mode)
+static inline bool gtod_is_based_on_tsc(int mode)
 {
        return mode == VDSO_CLOCKMODE_TSC || mode == VDSO_CLOCKMODE_HVCLOCK;
 }
@@ -5454,7 +5453,8 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
        if (events->flags & KVM_VCPUEVENT_VALID_NMI_PENDING) {
                vcpu->arch.nmi_pending = 0;
                atomic_set(&vcpu->arch.nmi_queued, events->nmi.pending);
-               kvm_make_request(KVM_REQ_NMI, vcpu);
+               if (events->nmi.pending)
+                       kvm_make_request(KVM_REQ_NMI, vcpu);
        }
        static_call(kvm_x86_set_nmi_mask)(vcpu, events->nmi.masked);
 
@@ -7016,6 +7016,9 @@ set_identity_unlock:
                r = -EEXIST;
                if (kvm->arch.vpit)
                        goto create_pit_unlock;
+               r = -ENOENT;
+               if (!pic_in_kernel(kvm))
+                       goto create_pit_unlock;
                r = -ENOMEM;
                kvm->arch.vpit = kvm_create_pit(kvm, u.pit_config.flags);
                if (kvm->arch.vpit)
index 20ef350a60fbb59a4b183bc3e54b1d517e6bba9b..10d5ed8b5990f4d2f64436b71905a9d817df11a1 100644 (file)
@@ -163,23 +163,23 @@ SYM_CODE_END(__get_user_8_handle_exception)
 #endif
 
 /* get_user */
-       _ASM_EXTABLE(1b, __get_user_handle_exception)
-       _ASM_EXTABLE(2b, __get_user_handle_exception)
-       _ASM_EXTABLE(3b, __get_user_handle_exception)
+       _ASM_EXTABLE_UA(1b, __get_user_handle_exception)
+       _ASM_EXTABLE_UA(2b, __get_user_handle_exception)
+       _ASM_EXTABLE_UA(3b, __get_user_handle_exception)
 #ifdef CONFIG_X86_64
-       _ASM_EXTABLE(4b, __get_user_handle_exception)
+       _ASM_EXTABLE_UA(4b, __get_user_handle_exception)
 #else
-       _ASM_EXTABLE(4b, __get_user_8_handle_exception)
-       _ASM_EXTABLE(5b, __get_user_8_handle_exception)
+       _ASM_EXTABLE_UA(4b, __get_user_8_handle_exception)
+       _ASM_EXTABLE_UA(5b, __get_user_8_handle_exception)
 #endif
 
 /* __get_user */
-       _ASM_EXTABLE(6b, __get_user_handle_exception)
-       _ASM_EXTABLE(7b, __get_user_handle_exception)
-       _ASM_EXTABLE(8b, __get_user_handle_exception)
+       _ASM_EXTABLE_UA(6b, __get_user_handle_exception)
+       _ASM_EXTABLE_UA(7b, __get_user_handle_exception)
+       _ASM_EXTABLE_UA(8b, __get_user_handle_exception)
 #ifdef CONFIG_X86_64
-       _ASM_EXTABLE(9b, __get_user_handle_exception)
+       _ASM_EXTABLE_UA(9b, __get_user_handle_exception)
 #else
-       _ASM_EXTABLE(9b, __get_user_8_handle_exception)
-       _ASM_EXTABLE(10b, __get_user_8_handle_exception)
+       _ASM_EXTABLE_UA(9b, __get_user_8_handle_exception)
+       _ASM_EXTABLE_UA(10b, __get_user_8_handle_exception)
 #endif
index 2877f59341775aa38a68d152f72e0d55606c1cac..975c9c18263d2afd926c12a8bfffe0c2d72d43cd 100644 (file)
@@ -133,15 +133,15 @@ SYM_CODE_START_LOCAL(__put_user_handle_exception)
        RET
 SYM_CODE_END(__put_user_handle_exception)
 
-       _ASM_EXTABLE(1b, __put_user_handle_exception)
-       _ASM_EXTABLE(2b, __put_user_handle_exception)
-       _ASM_EXTABLE(3b, __put_user_handle_exception)
-       _ASM_EXTABLE(4b, __put_user_handle_exception)
-       _ASM_EXTABLE(5b, __put_user_handle_exception)
-       _ASM_EXTABLE(6b, __put_user_handle_exception)
-       _ASM_EXTABLE(7b, __put_user_handle_exception)
-       _ASM_EXTABLE(9b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(1b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(2b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(3b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(4b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(5b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(6b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(7b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(9b, __put_user_handle_exception)
 #ifdef CONFIG_X86_32
-       _ASM_EXTABLE(8b, __put_user_handle_exception)
-       _ASM_EXTABLE(10b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(8b, __put_user_handle_exception)
+       _ASM_EXTABLE_UA(10b, __put_user_handle_exception)
 #endif
index 4b0d6fff88de5a544e2ef91a8c3f7c5fa1339aa5..1fb9a1644d944b825a7eb5735b68f48b4c8df9ce 100644 (file)
@@ -65,6 +65,8 @@ int xen_smp_intr_init(unsigned int cpu)
        char *resched_name, *callfunc_name, *debug_name;
 
        resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
+       if (!resched_name)
+               goto fail_mem;
        per_cpu(xen_resched_irq, cpu).name = resched_name;
        rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
                                    cpu,
@@ -77,6 +79,8 @@ int xen_smp_intr_init(unsigned int cpu)
        per_cpu(xen_resched_irq, cpu).irq = rc;
 
        callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu);
+       if (!callfunc_name)
+               goto fail_mem;
        per_cpu(xen_callfunc_irq, cpu).name = callfunc_name;
        rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR,
                                    cpu,
@@ -90,6 +94,9 @@ int xen_smp_intr_init(unsigned int cpu)
 
        if (!xen_fifo_events) {
                debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
+               if (!debug_name)
+                       goto fail_mem;
+
                per_cpu(xen_debug_irq, cpu).name = debug_name;
                rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu,
                                             xen_debug_interrupt,
@@ -101,6 +108,9 @@ int xen_smp_intr_init(unsigned int cpu)
        }
 
        callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu);
+       if (!callfunc_name)
+               goto fail_mem;
+
        per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name;
        rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR,
                                    cpu,
@@ -114,6 +124,8 @@ int xen_smp_intr_init(unsigned int cpu)
 
        return 0;
 
+ fail_mem:
+       rc = -ENOMEM;
  fail:
        xen_smp_intr_free(cpu);
        return rc;
index c812bf85021c02db59d107fda752dba2872e3b60..46c8596259d2d921fc0395a9eaf8dd444032029c 100644 (file)
@@ -13,7 +13,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key,
                                               bool branch)
 {
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                          "_nop\n\t"
                          ".pushsection __jump_table,  \"aw\"\n\t"
                          ".word 1b, %l[l_yes], %c0\n\t"
@@ -38,7 +38,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
         * make it reachable and wrap both into a no-transform block
         * to avoid any assembler interference with this.
         */
-       asm_volatile_goto("1:\n\t"
+       asm goto("1:\n\t"
                          ".begin no-transform\n\t"
                          "_j %l[l_yes]\n\t"
                          "2:\n\t"
index c8beec6d7df0863bb4811c12f5ff576e7a5121c7..04d44f0bcbc85d4898df728c8ceefb3f1b5bea39 100644 (file)
@@ -1353,6 +1353,13 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now)
 
        lockdep_assert_held(&iocg->waitq.lock);
 
+       /*
+        * If the delay is set by another CPU, we may be in the past. No need to
+        * change anything if so. This avoids decay calculation underflow.
+        */
+       if (time_before64(now->now, iocg->delay_at))
+               return false;
+
        /* calculate the current delay in effect - 1/2 every second */
        tdelta = now->now - iocg->delay_at;
        if (iocg->delay)
index 5ba3cd574eacbddc1b92bbaec3d79d81fb66ae7a..0c0e270a82650d9a0c6977931cd8a833b467f520 100644 (file)
@@ -163,9 +163,9 @@ static void wb_timestamp(struct rq_wb *rwb, unsigned long *var)
  */
 static bool wb_recent_wait(struct rq_wb *rwb)
 {
-       struct bdi_writeback *wb = &rwb->rqos.disk->bdi->wb;
+       struct backing_dev_info *bdi = rwb->rqos.disk->bdi;
 
-       return time_before(jiffies, wb->dirty_sleep + HZ);
+       return time_before(jiffies, bdi->last_bdp_sleep + HZ);
 }
 
 static inline struct rq_wait *get_rq_wait(struct rq_wb *rwb,
index 82c44d4899b9676d4d43c2f2af7fd9f95758b894..e24c829d7a0154f0ff016152e6913bff105cd93f 100644 (file)
@@ -91,13 +91,13 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
                if (!(msg->msg_flags & MSG_MORE)) {
                        err = hash_alloc_result(sk, ctx);
                        if (err)
-                               goto unlock_free;
+                               goto unlock_free_result;
                        ahash_request_set_crypt(&ctx->req, NULL,
                                                ctx->result, 0);
                        err = crypto_wait_req(crypto_ahash_final(&ctx->req),
                                              &ctx->wait);
                        if (err)
-                               goto unlock_free;
+                               goto unlock_free_result;
                }
                goto done_more;
        }
@@ -170,6 +170,7 @@ unlock:
 
 unlock_free:
        af_alg_free_sg(&ctx->sgl);
+unlock_free_result:
        hash_free_result(sk, ctx);
        ctx->more = false;
        goto unlock;
index eedddef9ce40cc40fa7a3c2cd3bcca7607be491b..e81918ca68b782c881bf6f868b441281e249e7f4 100644 (file)
@@ -148,6 +148,9 @@ static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb)
        if (!is_power_of_2(inst->alg.co.base.cra_blocksize))
                goto out_free_inst;
 
+       if (inst->alg.co.statesize)
+               goto out_free_inst;
+
        inst->alg.encrypt = crypto_cbc_encrypt;
        inst->alg.decrypt = crypto_cbc_decrypt;
 
index 9418c73ee8ef8ba025ef896ffe218b61b8058f75..4b06402269869335c324770fc572a57bea7316f7 100644 (file)
@@ -480,9 +480,8 @@ static int ivpu_pci_init(struct ivpu_device *vdev)
        /* Clear any pending errors */
        pcie_capability_clear_word(pdev, PCI_EXP_DEVSTA, 0x3f);
 
-       /* VPU 37XX does not require 10m D3hot delay */
-       if (ivpu_hw_gen(vdev) == IVPU_HW_37XX)
-               pdev->d3hot_delay = 0;
+       /* NPU does not require 10m D3hot delay */
+       pdev->d3hot_delay = 0;
 
        ret = pcim_enable_device(pdev);
        if (ret) {
index 6576232f3e678ee7c2532b07c830b74733c06960..5fa8bd4603d5be6f1fba8c43ba058e6a9b4f3676 100644 (file)
@@ -222,7 +222,6 @@ ivpu_fw_init_wa(struct ivpu_device *vdev)
        const struct vpu_firmware_header *fw_hdr = (const void *)vdev->fw->file->data;
 
        if (IVPU_FW_CHECK_API_VER_LT(vdev, fw_hdr, BOOT, 3, 17) ||
-           (ivpu_hw_gen(vdev) > IVPU_HW_37XX) ||
            (ivpu_test_mode & IVPU_TEST_MODE_D0I3_MSG_DISABLE))
                vdev->wa.disable_d0i3_msg = true;
 
index f15a93d83057822f2414aedb22359063fb99c6a1..89af1006df5587ba560415a7d669251648f3c3e8 100644 (file)
@@ -510,22 +510,12 @@ static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev)
        return ret;
 }
 
-static int ivpu_boot_pwr_domain_disable(struct ivpu_device *vdev)
-{
-       ivpu_boot_dpu_active_drive(vdev, false);
-       ivpu_boot_pwr_island_isolation_drive(vdev, true);
-       ivpu_boot_pwr_island_trickle_drive(vdev, false);
-       ivpu_boot_pwr_island_drive(vdev, false);
-
-       return ivpu_boot_wait_for_pwr_island_status(vdev, 0x0);
-}
-
 static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev)
 {
        u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES);
 
        val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, NOSNOOP_OVERRIDE_EN, val);
-       val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val);
+       val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val);
        val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val);
 
        REGV_WR32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, val);
@@ -616,12 +606,37 @@ static int ivpu_hw_37xx_info_init(struct ivpu_device *vdev)
        return 0;
 }
 
+static int ivpu_hw_37xx_ip_reset(struct ivpu_device *vdev)
+{
+       int ret;
+       u32 val;
+
+       if (IVPU_WA(punit_disabled))
+               return 0;
+
+       ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
+       if (ret) {
+               ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n");
+               return ret;
+       }
+
+       val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_IP_RESET);
+       val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, val);
+       REGB_WR32(VPU_37XX_BUTTRESS_VPU_IP_RESET, val);
+
+       ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
+       if (ret)
+               ivpu_err(vdev, "Timed out waiting for RESET completion\n");
+
+       return ret;
+}
+
 static int ivpu_hw_37xx_reset(struct ivpu_device *vdev)
 {
        int ret = 0;
 
-       if (ivpu_boot_pwr_domain_disable(vdev)) {
-               ivpu_err(vdev, "Failed to disable power domain\n");
+       if (ivpu_hw_37xx_ip_reset(vdev)) {
+               ivpu_err(vdev, "Failed to reset NPU\n");
                ret = -EIO;
        }
 
@@ -661,6 +676,11 @@ static int ivpu_hw_37xx_power_up(struct ivpu_device *vdev)
 {
        int ret;
 
+       /* PLL requests may fail when powering down, so issue WP 0 here */
+       ret = ivpu_pll_disable(vdev);
+       if (ret)
+               ivpu_warn(vdev, "Failed to disable PLL: %d\n", ret);
+
        ret = ivpu_hw_37xx_d0i3_disable(vdev);
        if (ret)
                ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);
index 704288084f37379eb6c7a1a5beb8f58ec3cea4a2..1c995307c1138885dc9cacd7ad73ca16633f2158 100644 (file)
@@ -530,7 +530,7 @@ static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev)
        u32 val = REGV_RD32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES);
 
        val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, SNOOP_OVERRIDE_EN, val);
-       val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val);
+       val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val);
        val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AR_SNOOP_OVERRIDE, val);
 
        REGV_WR32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, val);
@@ -704,7 +704,6 @@ static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev)
 {
        struct ivpu_hw_info *hw = vdev->hw;
        u32 tile_disable;
-       u32 tile_enable;
        u32 fuse;
 
        fuse = REGB_RD32(VPU_40XX_BUTTRESS_TILE_FUSE);
@@ -725,10 +724,6 @@ static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev)
        else
                ivpu_dbg(vdev, MISC, "Fuse: All %d tiles enabled\n", TILE_MAX_NUM);
 
-       tile_enable = (~tile_disable) & TILE_MAX_MASK;
-
-       hw->sku = REG_SET_FLD_NUM(SKU, HW_ID, LNL_HW_ID, hw->sku);
-       hw->sku = REG_SET_FLD_NUM(SKU, TILE, tile_enable, hw->sku);
        hw->tile_fuse = tile_disable;
        hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT;
 
index 0440bee3ecafd567da6cbf47584f3daa688b618d..e70cfb8593390e489e9f9868fb6c2420733ae241 100644 (file)
@@ -294,7 +294,7 @@ static int ivpu_job_signal_and_destroy(struct ivpu_device *vdev, u32 job_id, u32
                return -ENOENT;
 
        if (job->file_priv->has_mmu_faults)
-               job_status = VPU_JSM_STATUS_ABORTED;
+               job_status = DRM_IVPU_JOB_STATUS_ABORTED;
 
        job->bos[CMD_BUF_IDX]->job_status = job_status;
        dma_fence_signal(job->done_fence);
@@ -315,7 +315,7 @@ void ivpu_jobs_abort_all(struct ivpu_device *vdev)
        unsigned long id;
 
        xa_for_each(&vdev->submitted_jobs_xa, id, job)
-               ivpu_job_signal_and_destroy(vdev, id, VPU_JSM_STATUS_ABORTED);
+               ivpu_job_signal_and_destroy(vdev, id, DRM_IVPU_JOB_STATUS_ABORTED);
 }
 
 static int ivpu_job_submit(struct ivpu_job *job)
index 9a3122ffce03c1dc11311ab36f31f775f4fdf6fe..91bd640655ab363b51df17a25cb9589293adc804 100644 (file)
 
 #define IVPU_MMU_Q_COUNT_LOG2          4 /* 16 entries */
 #define IVPU_MMU_Q_COUNT               ((u32)1 << IVPU_MMU_Q_COUNT_LOG2)
-#define IVPU_MMU_Q_WRAP_BIT            (IVPU_MMU_Q_COUNT << 1)
-#define IVPU_MMU_Q_WRAP_MASK           (IVPU_MMU_Q_WRAP_BIT - 1)
-#define IVPU_MMU_Q_IDX_MASK            (IVPU_MMU_Q_COUNT - 1)
+#define IVPU_MMU_Q_WRAP_MASK            GENMASK(IVPU_MMU_Q_COUNT_LOG2, 0)
+#define IVPU_MMU_Q_IDX_MASK             (IVPU_MMU_Q_COUNT - 1)
 #define IVPU_MMU_Q_IDX(val)            ((val) & IVPU_MMU_Q_IDX_MASK)
+#define IVPU_MMU_Q_WRP(val)             ((val) & IVPU_MMU_Q_COUNT)
 
 #define IVPU_MMU_CMDQ_CMD_SIZE         16
 #define IVPU_MMU_CMDQ_SIZE             (IVPU_MMU_Q_COUNT * IVPU_MMU_CMDQ_CMD_SIZE)
@@ -475,20 +475,32 @@ static int ivpu_mmu_cmdq_wait_for_cons(struct ivpu_device *vdev)
        return 0;
 }
 
+static bool ivpu_mmu_queue_is_full(struct ivpu_mmu_queue *q)
+{
+       return ((IVPU_MMU_Q_IDX(q->prod) == IVPU_MMU_Q_IDX(q->cons)) &&
+               (IVPU_MMU_Q_WRP(q->prod) != IVPU_MMU_Q_WRP(q->cons)));
+}
+
+static bool ivpu_mmu_queue_is_empty(struct ivpu_mmu_queue *q)
+{
+       return ((IVPU_MMU_Q_IDX(q->prod) == IVPU_MMU_Q_IDX(q->cons)) &&
+               (IVPU_MMU_Q_WRP(q->prod) == IVPU_MMU_Q_WRP(q->cons)));
+}
+
 static int ivpu_mmu_cmdq_cmd_write(struct ivpu_device *vdev, const char *name, u64 data0, u64 data1)
 {
-       struct ivpu_mmu_queue *q = &vdev->mmu->cmdq;
-       u64 *queue_buffer = q->base;
-       int idx = IVPU_MMU_Q_IDX(q->prod) * (IVPU_MMU_CMDQ_CMD_SIZE / sizeof(*queue_buffer));
+       struct ivpu_mmu_queue *cmdq = &vdev->mmu->cmdq;
+       u64 *queue_buffer = cmdq->base;
+       int idx = IVPU_MMU_Q_IDX(cmdq->prod) * (IVPU_MMU_CMDQ_CMD_SIZE / sizeof(*queue_buffer));
 
-       if (!CIRC_SPACE(IVPU_MMU_Q_IDX(q->prod), IVPU_MMU_Q_IDX(q->cons), IVPU_MMU_Q_COUNT)) {
+       if (ivpu_mmu_queue_is_full(cmdq)) {
                ivpu_err(vdev, "Failed to write MMU CMD %s\n", name);
                return -EBUSY;
        }
 
        queue_buffer[idx] = data0;
        queue_buffer[idx + 1] = data1;
-       q->prod = (q->prod + 1) & IVPU_MMU_Q_WRAP_MASK;
+       cmdq->prod = (cmdq->prod + 1) & IVPU_MMU_Q_WRAP_MASK;
 
        ivpu_dbg(vdev, MMU, "CMD write: %s data: 0x%llx 0x%llx\n", name, data0, data1);
 
@@ -560,7 +572,6 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev)
        mmu->cmdq.cons = 0;
 
        memset(mmu->evtq.base, 0, IVPU_MMU_EVTQ_SIZE);
-       clflush_cache_range(mmu->evtq.base, IVPU_MMU_EVTQ_SIZE);
        mmu->evtq.prod = 0;
        mmu->evtq.cons = 0;
 
@@ -874,14 +885,10 @@ static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev)
        u32 *evt = evtq->base + (idx * IVPU_MMU_EVTQ_CMD_SIZE);
 
        evtq->prod = REGV_RD32(IVPU_MMU_REG_EVTQ_PROD_SEC);
-       if (!CIRC_CNT(IVPU_MMU_Q_IDX(evtq->prod), IVPU_MMU_Q_IDX(evtq->cons), IVPU_MMU_Q_COUNT))
+       if (ivpu_mmu_queue_is_empty(evtq))
                return NULL;
 
-       clflush_cache_range(evt, IVPU_MMU_EVTQ_CMD_SIZE);
-
        evtq->cons = (evtq->cons + 1) & IVPU_MMU_Q_WRAP_MASK;
-       REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, evtq->cons);
-
        return evt;
 }
 
@@ -902,6 +909,7 @@ void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev)
                }
 
                ivpu_mmu_user_context_mark_invalid(vdev, ssid);
+               REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons);
        }
 }
 
index f501f27ebafdf6687b5a46ca7e2387faa931af3e..5f73854234ba93da22b00113376c296df1ebd35a 100644 (file)
@@ -58,11 +58,14 @@ static int ivpu_suspend(struct ivpu_device *vdev)
 {
        int ret;
 
+       /* Save PCI state before powering down as it sometimes gets corrupted if NPU hangs */
+       pci_save_state(to_pci_dev(vdev->drm.dev));
+
        ret = ivpu_shutdown(vdev);
-       if (ret) {
+       if (ret)
                ivpu_err(vdev, "Failed to shutdown VPU: %d\n", ret);
-               return ret;
-       }
+
+       pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
 
        return ret;
 }
@@ -71,6 +74,9 @@ static int ivpu_resume(struct ivpu_device *vdev)
 {
        int ret;
 
+       pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0);
+       pci_restore_state(to_pci_dev(vdev->drm.dev));
+
 retry:
        ret = ivpu_hw_power_up(vdev);
        if (ret) {
@@ -120,15 +126,20 @@ static void ivpu_pm_recovery_work(struct work_struct *work)
 
        ivpu_fw_log_dump(vdev);
 
-retry:
-       ret = pci_try_reset_function(to_pci_dev(vdev->drm.dev));
-       if (ret == -EAGAIN && !drm_dev_is_unplugged(&vdev->drm)) {
-               cond_resched();
-               goto retry;
-       }
+       atomic_inc(&vdev->pm->reset_counter);
+       atomic_set(&vdev->pm->reset_pending, 1);
+       down_write(&vdev->pm->reset_lock);
+
+       ivpu_suspend(vdev);
+       ivpu_pm_prepare_cold_boot(vdev);
+       ivpu_jobs_abort_all(vdev);
+
+       ret = ivpu_resume(vdev);
+       if (ret)
+               ivpu_err(vdev, "Failed to resume NPU: %d\n", ret);
 
-       if (ret && ret != -EAGAIN)
-               ivpu_err(vdev, "Failed to reset VPU: %d\n", ret);
+       up_write(&vdev->pm->reset_lock);
+       atomic_set(&vdev->pm->reset_pending, 0);
 
        kobject_uevent_env(&vdev->drm.dev->kobj, KOBJ_CHANGE, evt);
        pm_runtime_mark_last_busy(vdev->drm.dev);
@@ -200,9 +211,6 @@ int ivpu_pm_suspend_cb(struct device *dev)
        ivpu_suspend(vdev);
        ivpu_pm_prepare_warm_boot(vdev);
 
-       pci_save_state(to_pci_dev(dev));
-       pci_set_power_state(to_pci_dev(dev), PCI_D3hot);
-
        ivpu_dbg(vdev, PM, "Suspend done.\n");
 
        return 0;
@@ -216,9 +224,6 @@ int ivpu_pm_resume_cb(struct device *dev)
 
        ivpu_dbg(vdev, PM, "Resume..\n");
 
-       pci_set_power_state(to_pci_dev(dev), PCI_D0);
-       pci_restore_state(to_pci_dev(dev));
-
        ret = ivpu_resume(vdev);
        if (ret)
                ivpu_err(vdev, "Failed to resume: %d\n", ret);
index 7b7c605166e0c1c7d2a4c9e1f1bce1f05799d4f6..fe825a432c5bfcce4776d83e0f072c9675507dae 100644 (file)
@@ -680,32 +680,6 @@ static void ghes_defer_non_standard_event(struct acpi_hest_generic_data *gdata,
 static DECLARE_RWSEM(cxl_cper_rw_sem);
 static cxl_cper_callback cper_callback;
 
-/* CXL Event record UUIDs are formatted as GUIDs and reported in section type */
-
-/*
- * General Media Event Record
- * CXL rev 3.0 Section 8.2.9.2.1.1; Table 8-43
- */
-#define CPER_SEC_CXL_GEN_MEDIA_GUID                                    \
-       GUID_INIT(0xfbcd0a77, 0xc260, 0x417f,                           \
-                 0x85, 0xa9, 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6)
-
-/*
- * DRAM Event Record
- * CXL rev 3.0 section 8.2.9.2.1.2; Table 8-44
- */
-#define CPER_SEC_CXL_DRAM_GUID                                         \
-       GUID_INIT(0x601dcbb3, 0x9c06, 0x4eab,                           \
-                 0xb8, 0xaf, 0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24)
-
-/*
- * Memory Module Event Record
- * CXL rev 3.0 section 8.2.9.2.1.3; Table 8-45
- */
-#define CPER_SEC_CXL_MEM_MODULE_GUID                                   \
-       GUID_INIT(0xfe927475, 0xdd59, 0x4339,                           \
-                 0xa5, 0x86, 0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74)
-
 static void cxl_cper_post_event(enum cxl_event_type event_type,
                                struct cxl_cper_event_rec *rec)
 {
index e327a0229dc173442b2789a402a8ea0adb931cdd..e7f713cd70d3fd7a413c2568b8dca8f8cc8ba2c4 100644 (file)
@@ -2930,6 +2930,8 @@ open_card_ubr0(struct idt77252_dev *card)
        vc->scq = alloc_scq(card, vc->class);
        if (!vc->scq) {
                printk("%s: can't get SCQ.\n", card->name);
+               kfree(card->vcs[0]);
+               card->vcs[0] = NULL;
                return -ENOMEM;
        }
 
index 026bdcb45127f530093cb4041f734d222e2fb005..0d957c5f1bcc987a585abaad9ed53623c33b4189 100644 (file)
@@ -9,6 +9,23 @@
 
 #define BLOCK_TEST_SIZE 12
 
+static void get_changed_bytes(void *orig, void *new, size_t size)
+{
+       char *o = orig;
+       char *n = new;
+       int i;
+
+       get_random_bytes(new, size);
+
+       /*
+        * This could be nicer and more efficient but we shouldn't
+        * super care.
+        */
+       for (i = 0; i < size; i++)
+               while (n[i] == o[i])
+                       get_random_bytes(&n[i], 1);
+}
+
 static const struct regmap_config test_regmap_config = {
        .max_register = BLOCK_TEST_SIZE,
        .reg_stride = 1,
@@ -1202,7 +1219,8 @@ static void raw_noinc_write(struct kunit *test)
        struct regmap *map;
        struct regmap_config config;
        struct regmap_ram_data *data;
-       unsigned int val, val_test, val_last;
+       unsigned int val;
+       u16 val_test, val_last;
        u16 val_array[BLOCK_TEST_SIZE];
 
        config = raw_regmap_config;
@@ -1251,7 +1269,7 @@ static void raw_sync(struct kunit *test)
        struct regmap *map;
        struct regmap_config config;
        struct regmap_ram_data *data;
-       u16 val[2];
+       u16 val[3];
        u16 *hw_buf;
        unsigned int rval;
        int i;
@@ -1265,17 +1283,13 @@ static void raw_sync(struct kunit *test)
 
        hw_buf = (u16 *)data->vals;
 
-       get_random_bytes(&val, sizeof(val));
+       get_changed_bytes(&hw_buf[2], &val[0], sizeof(val));
 
        /* Do a regular write and a raw write in cache only mode */
        regcache_cache_only(map, true);
-       KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val, sizeof(val)));
-       if (config.val_format_endian == REGMAP_ENDIAN_BIG)
-               KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 6,
-                                                     be16_to_cpu(val[0])));
-       else
-               KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 6,
-                                                     le16_to_cpu(val[0])));
+       KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val,
+                                                 sizeof(u16) * 2));
+       KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 4, val[2]));
 
        /* We should read back the new values, and defaults for the rest */
        for (i = 0; i < config.max_register + 1; i++) {
@@ -1284,24 +1298,34 @@ static void raw_sync(struct kunit *test)
                switch (i) {
                case 2:
                case 3:
-               case 6:
                        if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
                                KUNIT_EXPECT_EQ(test, rval,
-                                               be16_to_cpu(val[i % 2]));
+                                               be16_to_cpu(val[i - 2]));
                        } else {
                                KUNIT_EXPECT_EQ(test, rval,
-                                               le16_to_cpu(val[i % 2]));
+                                               le16_to_cpu(val[i - 2]));
                        }
                        break;
+               case 4:
+                       KUNIT_EXPECT_EQ(test, rval, val[i - 2]);
+                       break;
                default:
                        KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
                        break;
                }
        }
+
+       /*
+        * The value written via _write() was translated by the core,
+        * translate the original copy for comparison purposes.
+        */
+       if (config.val_format_endian == REGMAP_ENDIAN_BIG)
+               val[2] = cpu_to_be16(val[2]);
+       else
+               val[2] = cpu_to_le16(val[2]);
        
        /* The values should not appear in the "hardware" */
-       KUNIT_EXPECT_MEMNEQ(test, &hw_buf[2], val, sizeof(val));
-       KUNIT_EXPECT_MEMNEQ(test, &hw_buf[6], val, sizeof(u16));
+       KUNIT_EXPECT_MEMNEQ(test, &hw_buf[2], &val[0], sizeof(val));
 
        for (i = 0; i < config.max_register + 1; i++)
                data->written[i] = false;
@@ -1312,8 +1336,7 @@ static void raw_sync(struct kunit *test)
        KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
 
        /* The values should now appear in the "hardware" */
-       KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], val, sizeof(val));
-       KUNIT_EXPECT_MEMEQ(test, &hw_buf[6], val, sizeof(u16));
+       KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], &val[0], sizeof(val));
 
        regmap_exit(map);
 }
index 5bf98fd6a651a506ff294545d6241f608af34568..2bf14a0e2815f6292a02b3fa1e394489af780074 100644 (file)
@@ -1593,14 +1593,15 @@ static int virtblk_freeze(struct virtio_device *vdev)
 {
        struct virtio_blk *vblk = vdev->priv;
 
+       /* Ensure no requests in virtqueues before deleting vqs. */
+       blk_mq_freeze_queue(vblk->disk->queue);
+
        /* Ensure we don't receive any more interrupts */
        virtio_reset_device(vdev);
 
        /* Make sure no work handler is accessing the device. */
        flush_work(&vblk->config_work);
 
-       blk_mq_quiesce_queue(vblk->disk->queue);
-
        vdev->config->del_vqs(vdev);
        kfree(vblk->vqs);
 
@@ -1618,7 +1619,7 @@ static int virtblk_restore(struct virtio_device *vdev)
 
        virtio_device_ready(vdev);
 
-       blk_mq_unquiesce_queue(vblk->disk->queue);
+       blk_mq_unfreeze_queue(vblk->disk->queue);
        return 0;
 }
 #endif
index 3d5e6d705fc6ee3a0224a0b1fa57c32076fe306f..44b19e69617632bf4951d8da1e514f9c0c689d4b 100644 (file)
@@ -108,9 +108,8 @@ static inline void send_msg(struct cn_msg *msg)
                filter_data[1] = 0;
        }
 
-       if (cn_netlink_send_mult(msg, msg->len, 0, CN_IDX_PROC, GFP_NOWAIT,
-                            cn_filter, (void *)filter_data) == -ESRCH)
-               atomic_set(&proc_event_num_listeners, 0);
+       cn_netlink_send_mult(msg, msg->len, 0, CN_IDX_PROC, GFP_NOWAIT,
+                            cn_filter, (void *)filter_data);
 
        local_unlock(&local_event.lock);
 }
index e4d3f45242f63258ea0efc9f0a0a7ca9b411333c..b04bc1d3d627d447c2cfc10b9078b040800c8406 100644 (file)
@@ -534,10 +534,16 @@ EXPORT_SYMBOL_GPL(sev_platform_init);
 
 static int __sev_platform_shutdown_locked(int *error)
 {
-       struct sev_device *sev = psp_master->sev_data;
+       struct psp_device *psp = psp_master;
+       struct sev_device *sev;
        int ret;
 
-       if (!sev || sev->state == SEV_STATE_UNINIT)
+       if (!psp || !psp->sev_data)
+               return 0;
+
+       sev = psp->sev_data;
+
+       if (sev->state == SEV_STATE_UNINIT)
                return 0;
 
        ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error);
index 89445435303aac4d043c964a0ada866548889917..bdf117a33744be2db0468e869226ac8d45ef7a16 100644 (file)
@@ -338,7 +338,7 @@ TRACE_EVENT(cxl_general_media,
 
        TP_fast_assign(
                CXL_EVT_TP_fast_assign(cxlmd, log, rec->hdr);
-               memcpy(&__entry->hdr_uuid, &CXL_EVENT_GEN_MEDIA_UUID, sizeof(uuid_t));
+               __entry->hdr_uuid = CXL_EVENT_GEN_MEDIA_UUID;
 
                /* General Media */
                __entry->dpa = le64_to_cpu(rec->phys_addr);
@@ -425,7 +425,7 @@ TRACE_EVENT(cxl_dram,
 
        TP_fast_assign(
                CXL_EVT_TP_fast_assign(cxlmd, log, rec->hdr);
-               memcpy(&__entry->hdr_uuid, &CXL_EVENT_DRAM_UUID, sizeof(uuid_t));
+               __entry->hdr_uuid = CXL_EVENT_DRAM_UUID;
 
                /* DRAM */
                __entry->dpa = le64_to_cpu(rec->phys_addr);
@@ -573,7 +573,7 @@ TRACE_EVENT(cxl_memory_module,
 
        TP_fast_assign(
                CXL_EVT_TP_fast_assign(cxlmd, log, rec->hdr);
-               memcpy(&__entry->hdr_uuid, &CXL_EVENT_MEM_MODULE_UUID, sizeof(uuid_t));
+               __entry->hdr_uuid = CXL_EVENT_MEM_MODULE_UUID;
 
                /* Memory Module Event */
                __entry->event_type = rec->event_type;
index 314bb377546519ef25987b2e6f77827f590fe5fe..4ca9ad16cd957aaefaf50a74bbeb27ab3f3d1ec7 100644 (file)
@@ -1199,6 +1199,7 @@ int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
        unsigned long i;
        int ret = 0;
 
+       mutex_lock(&dpll_lock);
        xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED,
                                 ctx->idx) {
                if (!dpll_pin_available(pin))
@@ -1218,6 +1219,8 @@ int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
                }
                genlmsg_end(skb, hdr);
        }
+       mutex_unlock(&dpll_lock);
+
        if (ret == -EMSGSIZE) {
                ctx->idx = i;
                return skb->len;
@@ -1373,6 +1376,7 @@ int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
        unsigned long i;
        int ret = 0;
 
+       mutex_lock(&dpll_lock);
        xa_for_each_marked_start(&dpll_device_xa, i, dpll, DPLL_REGISTERED,
                                 ctx->idx) {
                hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
@@ -1389,6 +1393,8 @@ int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
                }
                genlmsg_end(skb, hdr);
        }
+       mutex_unlock(&dpll_lock);
+
        if (ret == -EMSGSIZE) {
                ctx->idx = i;
                return skb->len;
@@ -1439,20 +1445,6 @@ dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
        mutex_unlock(&dpll_lock);
 }
 
-int dpll_lock_dumpit(struct netlink_callback *cb)
-{
-       mutex_lock(&dpll_lock);
-
-       return 0;
-}
-
-int dpll_unlock_dumpit(struct netlink_callback *cb)
-{
-       mutex_unlock(&dpll_lock);
-
-       return 0;
-}
-
 int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
                      struct genl_info *info)
 {
index eaee5be7aa642a9359c0b438e7157eec830b6519..1e95f5397cfce65270fbc88d8916a24386258047 100644 (file)
@@ -95,9 +95,7 @@ static const struct genl_split_ops dpll_nl_ops[] = {
        },
        {
                .cmd    = DPLL_CMD_DEVICE_GET,
-               .start  = dpll_lock_dumpit,
                .dumpit = dpll_nl_device_get_dumpit,
-               .done   = dpll_unlock_dumpit,
                .flags  = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
        },
        {
@@ -129,9 +127,7 @@ static const struct genl_split_ops dpll_nl_ops[] = {
        },
        {
                .cmd            = DPLL_CMD_PIN_GET,
-               .start          = dpll_lock_dumpit,
                .dumpit         = dpll_nl_pin_get_dumpit,
-               .done           = dpll_unlock_dumpit,
                .policy         = dpll_pin_get_dump_nl_policy,
                .maxattr        = DPLL_A_PIN_ID,
                .flags          = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
index 92d4c9c4f788dc1b36c7b076a980afd2903aba68..f491262bee4f0c16e97624353bef6a4938b761aa 100644 (file)
@@ -30,8 +30,6 @@ dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
 void
 dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
                   struct genl_info *info);
-int dpll_lock_dumpit(struct netlink_callback *cb);
-int dpll_unlock_dumpit(struct netlink_callback *cb);
 
 int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info);
 int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info);
index 6ac5ff20a2fe22f1c3c5a7010ca0af87caf4c446..8aaa7fcb2630dcf47a5325982cbed1037f685b3b 100644 (file)
@@ -429,7 +429,23 @@ static void bm_work(struct work_struct *work)
         */
        card->bm_generation = generation;
 
-       if (root_device == NULL) {
+       if (card->gap_count == 0) {
+               /*
+                * If self IDs have inconsistent gap counts, do a
+                * bus reset ASAP. The config rom read might never
+                * complete, so don't wait for it. However, still
+                * send a PHY configuration packet prior to the
+                * bus reset. The PHY configuration packet might
+                * fail, but 1394-2008 8.4.5.2 explicitly permits
+                * it in this case, so it should be safe to try.
+                */
+               new_root_id = local_id;
+               /*
+                * We must always send a bus reset if the gap count
+                * is inconsistent, so bypass the 5-reset limit.
+                */
+               card->bm_retries = 0;
+       } else if (root_device == NULL) {
                /*
                 * Either link_on is false, or we failed to read the
                 * config rom.  In either case, pick another root.
index 83f5bb57fa4c466334a90c2195c06ce7443d1b6a..83092d93f36a63087ffbd8b6460d38a824e9cbb1 100644 (file)
@@ -107,7 +107,7 @@ static int __init arm_enable_runtime_services(void)
                efi_memory_desc_t *md;
 
                for_each_efi_memory_desc(md) {
-                       int md_size = md->num_pages << EFI_PAGE_SHIFT;
+                       u64 md_size = md->num_pages << EFI_PAGE_SHIFT;
                        struct resource *res;
 
                        if (!(md->attribute & EFI_MEMORY_SP))
index 35c37f667781c7071c714aef274e68dbddca026b..9b3884ff81e699f2308a3cf618e774ad9a67e6a3 100644 (file)
@@ -523,6 +523,17 @@ static void cper_print_tstamp(const char *pfx,
        }
 }
 
+struct ignore_section {
+       guid_t guid;
+       const char *name;
+};
+
+static const struct ignore_section ignore_sections[] = {
+       { .guid = CPER_SEC_CXL_GEN_MEDIA_GUID, .name = "CXL General Media Event" },
+       { .guid = CPER_SEC_CXL_DRAM_GUID, .name = "CXL DRAM Event" },
+       { .guid = CPER_SEC_CXL_MEM_MODULE_GUID, .name = "CXL Memory Module Event" },
+};
+
 static void
 cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata,
                           int sec_no)
@@ -543,6 +554,14 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata
                printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text);
 
        snprintf(newpfx, sizeof(newpfx), "%s ", pfx);
+
+       for (int i = 0; i < ARRAY_SIZE(ignore_sections); i++) {
+               if (guid_equal(sec_type, &ignore_sections[i].guid)) {
+                       printk("%ssection_type: %s\n", newpfx, ignore_sections[i].name);
+                       return;
+               }
+       }
+
        if (guid_equal(sec_type, &CPER_SEC_PROC_GENERIC)) {
                struct cper_sec_proc_generic *proc_err = acpi_hest_get_payload(gdata);
 
index d4987d013080174bda0e462f029c03192897bebb..a00e07b853f221721e1bcd2f801cadcc5bcb67cf 100644 (file)
@@ -143,15 +143,6 @@ static __init int is_usable_memory(efi_memory_desc_t *md)
        case EFI_BOOT_SERVICES_DATA:
        case EFI_CONVENTIONAL_MEMORY:
        case EFI_PERSISTENT_MEMORY:
-               /*
-                * Special purpose memory is 'soft reserved', which means it
-                * is set aside initially, but can be hotplugged back in or
-                * be assigned to the dax driver after boot.
-                */
-               if (efi_soft_reserve_enabled() &&
-                   (md->attribute & EFI_MEMORY_SP))
-                       return false;
-
                /*
                 * According to the spec, these regions are no longer reserved
                 * after calling ExitBootServices(). However, we can only use
@@ -196,6 +187,16 @@ static __init void reserve_regions(void)
                size = npages << PAGE_SHIFT;
 
                if (is_memory(md)) {
+                       /*
+                        * Special purpose memory is 'soft reserved', which
+                        * means it is set aside initially. Don't add a memblock
+                        * for it now so that it can be hotplugged back in or
+                        * be assigned to the dax driver after boot.
+                        */
+                       if (efi_soft_reserve_enabled() &&
+                           (md->attribute & EFI_MEMORY_SP))
+                               continue;
+
                        early_init_dt_add_memory_arch(paddr, size);
 
                        if (!is_usable_memory(md))
index 06964a3c130f6addeed20eca1ed26153a2260854..73f4810f6db38ecc933f9a6ac2bed5ae57709148 100644 (file)
@@ -28,7 +28,7 @@ cflags-$(CONFIG_ARM)          += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
                                   -DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \
                                   -DEFI_HAVE_STRCMP -fno-builtin -fpic \
                                   $(call cc-option,-mno-single-pic-base)
-cflags-$(CONFIG_RISCV)         += -fpic -DNO_ALTERNATIVE
+cflags-$(CONFIG_RISCV)         += -fpic -DNO_ALTERNATIVE -mno-relax
 cflags-$(CONFIG_LOONGARCH)     += -fpie
 
 cflags-$(CONFIG_EFI_PARAMS_FROM_FDT)   += -I$(srctree)/scripts/dtc/libfdt
@@ -143,7 +143,7 @@ STUBCOPY_RELOC-$(CONFIG_ARM64)      := R_AARCH64_ABS
 # exist.
 STUBCOPY_FLAGS-$(CONFIG_RISCV) += --prefix-alloc-sections=.init \
                                   --prefix-symbols=__efistub_
-STUBCOPY_RELOC-$(CONFIG_RISCV) := R_RISCV_HI20
+STUBCOPY_RELOC-$(CONFIG_RISCV) := -E R_RISCV_HI20\|R_RISCV_$(BITS)\|R_RISCV_RELAX
 
 # For LoongArch, keep all the symbols in .init section and make sure that no
 # absolute symbols references exist.
index 6b83c492c3b8260d52e16bb73a1d5abaa4cb943d..31928bd87e0fff5a0666234ef8328cf5d4f564df 100644 (file)
@@ -14,6 +14,7 @@
  * @max:       the address that the last allocated memory page shall not
  *             exceed
  * @align:     minimum alignment of the base of the allocation
+ * @memory_type: the type of memory to allocate
  *
  * Allocate pages as EFI_LOADER_DATA. The allocated pages are aligned according
  * to @align, which should be >= EFI_ALLOC_ALIGN. The last allocated page will
index 212687c30d79c4b0b307af0b8d3c7b52502e6a95..c04b82ea40f2169b6764ff69a14ff3acc5a8795d 100644 (file)
@@ -956,7 +956,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out);
 
 efi_status_t efi_random_alloc(unsigned long size, unsigned long align,
                              unsigned long *addr, unsigned long random_seed,
-                             int memory_type, unsigned long alloc_limit);
+                             int memory_type, unsigned long alloc_min,
+                             unsigned long alloc_max);
 
 efi_status_t efi_random_get_seed(void);
 
index 62d63f7a2645bf82525d79b5d8825e9bea023404..1a9808012abd36ee7f58ad0baf818cbae6df1b0b 100644 (file)
@@ -119,7 +119,7 @@ efi_status_t efi_kaslr_relocate_kernel(unsigned long *image_addr,
                 */
                status = efi_random_alloc(*reserve_size, min_kimg_align,
                                          reserve_addr, phys_seed,
-                                         EFI_LOADER_CODE, EFI_ALLOC_LIMIT);
+                                         EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
                if (status != EFI_SUCCESS)
                        efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
        } else {
index 674a064b8f7adc68edf2412bb8e012250077c717..4e96a855fdf47b5b064b63b729d7dc989cd2b949 100644 (file)
@@ -17,7 +17,7 @@
 static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
                                         unsigned long size,
                                         unsigned long align_shift,
-                                        u64 alloc_limit)
+                                        u64 alloc_min, u64 alloc_max)
 {
        unsigned long align = 1UL << align_shift;
        u64 first_slot, last_slot, region_end;
@@ -30,11 +30,11 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
                return 0;
 
        region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
-                        alloc_limit);
+                        alloc_max);
        if (region_end < size)
                return 0;
 
-       first_slot = round_up(md->phys_addr, align);
+       first_slot = round_up(max(md->phys_addr, alloc_min), align);
        last_slot = round_down(region_end - size + 1, align);
 
        if (first_slot > last_slot)
@@ -56,7 +56,8 @@ efi_status_t efi_random_alloc(unsigned long size,
                              unsigned long *addr,
                              unsigned long random_seed,
                              int memory_type,
-                             unsigned long alloc_limit)
+                             unsigned long alloc_min,
+                             unsigned long alloc_max)
 {
        unsigned long total_slots = 0, target_slot;
        unsigned long total_mirrored_slots = 0;
@@ -78,7 +79,8 @@ efi_status_t efi_random_alloc(unsigned long size,
                efi_memory_desc_t *md = (void *)map->map + map_offset;
                unsigned long slots;
 
-               slots = get_entry_num_slots(md, size, ilog2(align), alloc_limit);
+               slots = get_entry_num_slots(md, size, ilog2(align), alloc_min,
+                                           alloc_max);
                MD_NUM_SLOTS(md) = slots;
                total_slots += slots;
                if (md->attribute & EFI_MEMORY_MORE_RELIABLE)
index 0d510c9a06a45925922595f1e44c7ee3b2a170a6..99429bc4b0c7eb0c639b84934fe614f8f8cb5721 100644 (file)
@@ -223,8 +223,8 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
        }
 }
 
-void efi_adjust_memory_range_protection(unsigned long start,
-                                       unsigned long size)
+efi_status_t efi_adjust_memory_range_protection(unsigned long start,
+                                               unsigned long size)
 {
        efi_status_t status;
        efi_gcd_memory_space_desc_t desc;
@@ -236,13 +236,17 @@ void efi_adjust_memory_range_protection(unsigned long start,
        rounded_end = roundup(start + size, EFI_PAGE_SIZE);
 
        if (memattr != NULL) {
-               efi_call_proto(memattr, clear_memory_attributes, rounded_start,
-                              rounded_end - rounded_start, EFI_MEMORY_XP);
-               return;
+               status = efi_call_proto(memattr, clear_memory_attributes,
+                                       rounded_start,
+                                       rounded_end - rounded_start,
+                                       EFI_MEMORY_XP);
+               if (status != EFI_SUCCESS)
+                       efi_warn("Failed to clear EFI_MEMORY_XP attribute\n");
+               return status;
        }
 
        if (efi_dxe_table == NULL)
-               return;
+               return EFI_SUCCESS;
 
        /*
         * Don't modify memory region attributes, they are
@@ -255,7 +259,7 @@ void efi_adjust_memory_range_protection(unsigned long start,
                status = efi_dxe_call(get_memory_space_descriptor, start, &desc);
 
                if (status != EFI_SUCCESS)
-                       return;
+                       break;
 
                next = desc.base_address + desc.length;
 
@@ -280,8 +284,10 @@ void efi_adjust_memory_range_protection(unsigned long start,
                                 unprotect_start,
                                 unprotect_start + unprotect_size,
                                 status);
+                       break;
                }
        }
+       return EFI_SUCCESS;
 }
 
 static void setup_unaccepted_memory(void)
@@ -793,6 +799,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
 
        status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
                                  seed[0], EFI_LOADER_CODE,
+                                 LOAD_PHYSICAL_ADDR,
                                  EFI_X86_KERNEL_ALLOC_LIMIT);
        if (status != EFI_SUCCESS)
                return status;
@@ -805,9 +812,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
 
        *kernel_entry = addr + entry;
 
-       efi_adjust_memory_range_protection(addr, kernel_total_size);
-
-       return EFI_SUCCESS;
+       return efi_adjust_memory_range_protection(addr, kernel_total_size);
 }
 
 static void __noreturn enter_kernel(unsigned long kernel_addr,
index 37c5a36b9d8cf9b2cad93f228502fd336d142908..1c20e99a6494423787ef1dd091739ed9cbc89a24 100644 (file)
@@ -5,8 +5,8 @@
 extern void trampoline_32bit_src(void *, bool);
 extern const u16 trampoline_ljmp_imm_offset;
 
-void efi_adjust_memory_range_protection(unsigned long start,
-                                       unsigned long size);
+efi_status_t efi_adjust_memory_range_protection(unsigned long start,
+                                               unsigned long size);
 
 #ifdef CONFIG_X86_64
 efi_status_t efi_setup_5level_paging(void);
index bdb17eac0cb401befbcc8b13820f9a3b416b6f19..1ceace956758682f592f6fe3f280b7260f7ca562 100644 (file)
@@ -119,7 +119,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
                }
 
                status = efi_random_alloc(alloc_size, min_kimg_align, &image_base,
-                                         seed, EFI_LOADER_CODE, EFI_ALLOC_LIMIT);
+                                         seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
                if (status != EFI_SUCCESS) {
                        efi_err("Failed to allocate memory\n");
                        goto free_cmdline;
index 09525fb5c240e6686ff5588c55998d5815e20ff7..01f0f90ea4183119b0a4eedf82a3fe81f1b2f480 100644 (file)
@@ -85,7 +85,7 @@ static int __init riscv_enable_runtime_services(void)
                efi_memory_desc_t *md;
 
                for_each_efi_memory_desc(md) {
-                       int md_size = md->num_pages << EFI_PAGE_SHIFT;
+                       u64 md_size = md->num_pages << EFI_PAGE_SHIFT;
                        struct resource *res;
 
                        if (!(md->attribute & EFI_MEMORY_SP))
index 44c8f5743a2416087b523e973967e993e8a192a1..8b3a0f45b57456b13a04ecf4bf706b8cbf27b8dd 100644 (file)
@@ -1005,15 +1005,15 @@ err_remove_of_chip:
 err_free_gpiochip_mask:
        gpiochip_remove_pin_ranges(gc);
        gpiochip_free_valid_mask(gc);
+err_remove_from_list:
+       spin_lock_irqsave(&gpio_lock, flags);
+       list_del(&gdev->list);
+       spin_unlock_irqrestore(&gpio_lock, flags);
        if (gdev->dev.release) {
                /* release() has been registered by gpiochip_setup_dev() */
                gpio_device_put(gdev);
                goto err_print_message;
        }
-err_remove_from_list:
-       spin_lock_irqsave(&gpio_lock, flags);
-       list_del(&gdev->list);
-       spin_unlock_irqrestore(&gpio_lock, flags);
 err_free_label:
        kfree_const(gdev->label);
 err_free_descs:
index 3d8a48f46b015613dc44517ebd20d5250df5a3b1..79827a6dcd7f5cbbf30d61f6701ecee8ae6614fa 100644 (file)
@@ -200,6 +200,7 @@ extern uint amdgpu_dc_debug_mask;
 extern uint amdgpu_dc_visual_confirm;
 extern uint amdgpu_dm_abm_level;
 extern int amdgpu_backlight;
+extern int amdgpu_damage_clips;
 extern struct amdgpu_mgpu_info mgpu_info;
 extern int amdgpu_ras_enable;
 extern uint amdgpu_ras_mask;
@@ -1078,6 +1079,8 @@ struct amdgpu_device {
        bool                            in_s3;
        bool                            in_s4;
        bool                            in_s0ix;
+       /* indicate amdgpu suspension status */
+       bool                            suspend_complete;
 
        enum pp_mp1_state               mp1_state;
        struct amdgpu_doorbell_index doorbell_index;
@@ -1547,9 +1550,11 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
 #if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)
 bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev);
 bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);
+void amdgpu_choose_low_power_state(struct amdgpu_device *adev);
 #else
 static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }
 static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; }
+static inline void amdgpu_choose_low_power_state(struct amdgpu_device *adev) { }
 #endif
 
 #if defined(CONFIG_DRM_AMD_DC)
index 2deebece810e78a7ce039772a839684f570bceca..cc21ed67a33075d4f197f2217b883faacc777f3d 100644 (file)
@@ -1519,4 +1519,19 @@ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
 #endif /* CONFIG_AMD_PMC */
 }
 
+/**
+ * amdgpu_choose_low_power_state
+ *
+ * @adev: amdgpu_device_pointer
+ *
+ * Choose the target low power state for the GPU
+ */
+void amdgpu_choose_low_power_state(struct amdgpu_device *adev)
+{
+       if (amdgpu_acpi_is_s0ix_active(adev))
+               adev->in_s0ix = true;
+       else if (amdgpu_acpi_is_s3_active(adev))
+               adev->in_s3 = true;
+}
+
 #endif /* CONFIG_SUSPEND */
index fdde7488d0ed9a8ff93f4a4cc58c123b904236c7..94bdb5fa6ebc6ac7715a64191b5050a9670bf673 100644 (file)
@@ -4514,13 +4514,15 @@ int amdgpu_device_prepare(struct drm_device *dev)
        struct amdgpu_device *adev = drm_to_adev(dev);
        int i, r;
 
+       amdgpu_choose_low_power_state(adev);
+
        if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
 
        /* Evict the majority of BOs before starting suspend sequence */
        r = amdgpu_device_evict_resources(adev);
        if (r)
-               return r;
+               goto unprepare;
 
        for (i = 0; i < adev->num_ip_blocks; i++) {
                if (!adev->ip_blocks[i].status.valid)
@@ -4529,10 +4531,15 @@ int amdgpu_device_prepare(struct drm_device *dev)
                        continue;
                r = adev->ip_blocks[i].version->funcs->prepare_suspend((void *)adev);
                if (r)
-                       return r;
+                       goto unprepare;
        }
 
        return 0;
+
+unprepare:
+       adev->in_s0ix = adev->in_s3 = false;
+
+       return r;
 }
 
 /**
@@ -4569,7 +4576,6 @@ 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 971acf01bea6063cfcca6275a21b12662cfbd824..586f4d03039dfb5177a27fce81fbdbead88e0235 100644 (file)
@@ -211,6 +211,7 @@ int amdgpu_seamless = -1; /* auto */
 uint amdgpu_debug_mask;
 int amdgpu_agp = -1; /* auto */
 int amdgpu_wbrf = -1;
+int amdgpu_damage_clips = -1; /* auto */
 
 static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
 
@@ -859,6 +860,18 @@ int amdgpu_backlight = -1;
 MODULE_PARM_DESC(backlight, "Backlight control (0 = pwm, 1 = aux, -1 auto (default))");
 module_param_named(backlight, amdgpu_backlight, bint, 0444);
 
+/**
+ * DOC: damageclips (int)
+ * Enable or disable damage clips support. If damage clips support is disabled,
+ * we will force full frame updates, irrespective of what user space sends to
+ * us.
+ *
+ * Defaults to -1 (where it is enabled unless a PSR-SU display is detected).
+ */
+MODULE_PARM_DESC(damageclips,
+                "Damage clips support (0 = disable, 1 = enable, -1 auto (default))");
+module_param_named(damageclips, amdgpu_damage_clips, int, 0444);
+
 /**
  * DOC: tmz (int)
  * Trusted Memory Zone (TMZ) is a method to protect data being written
@@ -2476,6 +2489,7 @@ static int amdgpu_pmops_suspend(struct device *dev)
        struct drm_device *drm_dev = dev_get_drvdata(dev);
        struct amdgpu_device *adev = drm_to_adev(drm_dev);
 
+       adev->suspend_complete = false;
        if (amdgpu_acpi_is_s0ix_active(adev))
                adev->in_s0ix = true;
        else if (amdgpu_acpi_is_s3_active(adev))
@@ -2490,6 +2504,7 @@ static int amdgpu_pmops_suspend_noirq(struct device *dev)
        struct drm_device *drm_dev = dev_get_drvdata(dev);
        struct amdgpu_device *adev = drm_to_adev(drm_dev);
 
+       adev->suspend_complete = true;
        if (amdgpu_acpi_should_gpu_reset(adev))
                return amdgpu_asic_reset(adev);
 
index b9674c57c4365fb5ebdf9644fc4ac0a31b955da8..6ddc8e3360e220644618b26059d735e6bbda10e4 100644 (file)
@@ -723,8 +723,15 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable)
 
                if (adev->gfx.gfx_off_req_count == 0 &&
                    !adev->gfx.gfx_off_state) {
-                       schedule_delayed_work(&adev->gfx.gfx_off_delay_work,
+                       /* 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,
                                              delay);
+                       }
                }
        } else {
                if (adev->gfx.gfx_off_req_count == 0) {
index 468a67b302d4c140c9d7cf09bc92566404180e75..ca5c86e5f7cd671a651d61357ab52d3c53a1e7f3 100644 (file)
@@ -362,7 +362,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
                }
        }
 
-       if (copy_to_user((char *)buf, context->mem_context.shared_buf, shared_buf_len))
+       if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len))
                ret = -EFAULT;
 
 err_free_shared_buf:
index 69c500910746018281471ad6d27350aaf2461702..3bc6943365a4ff36a32827ae2d477aac6883631d 100644 (file)
@@ -3034,6 +3034,14 @@ static int gfx_v9_0_cp_gfx_start(struct amdgpu_device *adev)
 
        gfx_v9_0_cp_gfx_enable(adev, true);
 
+       /* Now only limit the quirk on the APU gfx9 series and already
+        * confirmed that the APU gfx10/gfx11 needn't such update.
+        */
+       if (adev->flags & AMD_IS_APU &&
+                       adev->in_s3 && !adev->suspend_complete) {
+               DRM_INFO(" Will skip the CSB packet resubmit\n");
+               return 0;
+       }
        r = amdgpu_ring_alloc(ring, gfx_v9_0_get_csb_size(adev) + 4 + 3);
        if (r) {
                DRM_ERROR("amdgpu: cp failed to lock ring (%d).\n", r);
index 40a00ea0009f6aca367c68a43e11ae608f71d416..e67a62db9e12629b40c92f322922cc763ce53ce7 100644 (file)
@@ -1947,14 +1947,6 @@ static int gmc_v9_0_init_mem_ranges(struct amdgpu_device *adev)
 
 static void gmc_v9_4_3_init_vram_info(struct amdgpu_device *adev)
 {
-       static const u32 regBIF_BIOS_SCRATCH_4 = 0x50;
-       u32 vram_info;
-
-       /* Only for dGPU, vendor informaton is reliable */
-       if (!amdgpu_sriov_vf(adev) && !(adev->flags & AMD_IS_APU)) {
-               vram_info = RREG32(regBIF_BIOS_SCRATCH_4);
-               adev->gmc.vram_vendor = vram_info & 0xF;
-       }
        adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
        adev->gmc.vram_width = 128 * 64;
 }
index bc38b90f8cf88e8fee393e8e52214ac72f0aa8a6..88ea58d5c4abf5b0f20abff28f9833f402e4b016 100644 (file)
@@ -674,14 +674,6 @@ static int jpeg_v4_0_set_powergating_state(void *handle,
        return ret;
 }
 
-static int jpeg_v4_0_set_interrupt_state(struct amdgpu_device *adev,
-                                       struct amdgpu_irq_src *source,
-                                       unsigned type,
-                                       enum amdgpu_interrupt_state state)
-{
-       return 0;
-}
-
 static int jpeg_v4_0_set_ras_interrupt_state(struct amdgpu_device *adev,
                                        struct amdgpu_irq_src *source,
                                        unsigned int type,
@@ -765,7 +757,6 @@ static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev)
 }
 
 static const struct amdgpu_irq_src_funcs jpeg_v4_0_irq_funcs = {
-       .set = jpeg_v4_0_set_interrupt_state,
        .process = jpeg_v4_0_process_interrupt,
 };
 
index 6ede85b28cc8c0bbfd6a7e94c6a3d1a677e958bf..78b74daf4eebfc30f04ee4aaf6d0ff92891ff30f 100644 (file)
@@ -181,7 +181,6 @@ static int jpeg_v4_0_5_hw_fini(void *handle)
                        RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
                        jpeg_v4_0_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
        }
-       amdgpu_irq_put(adev, &adev->jpeg.inst->irq, 0);
 
        return 0;
 }
@@ -516,14 +515,6 @@ static int jpeg_v4_0_5_set_powergating_state(void *handle,
        return ret;
 }
 
-static int jpeg_v4_0_5_set_interrupt_state(struct amdgpu_device *adev,
-                                       struct amdgpu_irq_src *source,
-                                       unsigned type,
-                                       enum amdgpu_interrupt_state state)
-{
-       return 0;
-}
-
 static int jpeg_v4_0_5_process_interrupt(struct amdgpu_device *adev,
                                      struct amdgpu_irq_src *source,
                                      struct amdgpu_iv_entry *entry)
@@ -603,7 +594,6 @@ static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev)
 }
 
 static const struct amdgpu_irq_src_funcs jpeg_v4_0_5_irq_funcs = {
-       .set = jpeg_v4_0_5_set_interrupt_state,
        .process = jpeg_v4_0_5_process_interrupt,
 };
 
index e90f33780803458c32843f2599c07e4f598ca659..b4723d68eab0f939ba057b67cf7712ddb512c8c8 100644 (file)
@@ -431,6 +431,12 @@ static void nbio_v7_9_init_registers(struct amdgpu_device *adev)
        u32 inst_mask;
        int i;
 
+       if (amdgpu_sriov_vf(adev))
+               adev->rmmio_remap.reg_offset =
+                       SOC15_REG_OFFSET(
+                               NBIO, 0,
+                               regBIF_BX_DEV0_EPF0_VF0_HDP_MEM_COHERENCY_FLUSH_CNTL)
+                       << 2;
        WREG32_SOC15(NBIO, 0, regXCC_DOORBELL_FENCE,
                0xff & ~(adev->gfx.xcc_mask));
 
index 15033efec2bac0148e5d9381027a6ee3e70334b7..c64c01e2944a2e4c1f4177355771a1b47cfcc666 100644 (file)
@@ -1298,10 +1298,32 @@ static int soc15_common_suspend(void *handle)
        return soc15_common_hw_fini(adev);
 }
 
+static bool soc15_need_reset_on_resume(struct amdgpu_device *adev)
+{
+       u32 sol_reg;
+
+       sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
+
+       /* Will reset for the following suspend abort cases.
+        * 1) Only reset limit on APU side, dGPU hasn't checked yet.
+        * 2) S3 suspend abort and TOS already launched.
+        */
+       if (adev->flags & AMD_IS_APU && adev->in_s3 &&
+                       !adev->suspend_complete &&
+                       sol_reg)
+               return true;
+
+       return false;
+}
+
 static int soc15_common_resume(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (soc15_need_reset_on_resume(adev)) {
+               dev_info(adev->dev, "S3 suspend abort case, let's reset ASIC.\n");
+               soc15_asic_reset(adev);
+       }
        return soc15_common_hw_init(adev);
 }
 
index 48c6efcdeac974ba109224510442b0488e1875d0..4d7188912edfee820dca2ac854b55314dc2f1b27 100644 (file)
@@ -50,13 +50,13 @@ static const struct amd_ip_funcs soc21_common_ip_funcs;
 /* SOC21 */
 static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_encode_array_vcn0[] = {
        {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
-       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 0)},
        {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
 };
 
 static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_encode_array_vcn1[] = {
        {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
-       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 0)},
 };
 
 static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_encode_vcn0 = {
index d722cbd317834a8a893a0ed5a847feb3a51d6961..826bc4f6c8a7043853d0b8e21bad73660c6a8a8c 100644 (file)
@@ -55,8 +55,8 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
        m = get_mqd(mqd);
 
        if (has_wa_flag) {
-               uint32_t wa_mask = minfo->update_flag == UPDATE_FLAG_DBG_WA_ENABLE ?
-                                               0xffff : 0xffffffff;
+               uint32_t wa_mask =
+                       (minfo->update_flag & UPDATE_FLAG_DBG_WA_ENABLE) ? 0xffff : 0xffffffff;
 
                m->compute_static_thread_mgmt_se0 = wa_mask;
                m->compute_static_thread_mgmt_se1 = wa_mask;
index 42d881809dc70e230133674e4b12f6f68567837a..697b6d530d12ef30ed06a22d3cf5c15fa740b62a 100644 (file)
@@ -303,6 +303,15 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
                update_cu_mask(mm, mqd, minfo, 0);
        set_priority(m, q);
 
+       if (minfo && KFD_GC_VERSION(mm->dev) >= IP_VERSION(9, 4, 2)) {
+               if (minfo->update_flag & UPDATE_FLAG_IS_GWS)
+                       m->compute_resource_limits |=
+                               COMPUTE_RESOURCE_LIMITS__FORCE_SIMD_DIST_MASK;
+               else
+                       m->compute_resource_limits &=
+                               ~COMPUTE_RESOURCE_LIMITS__FORCE_SIMD_DIST_MASK;
+       }
+
        q->is_active = QUEUE_IS_ACTIVE(*q);
 }
 
index 677281c0793e23a694eb5a7bba9b5f9fd48f61d8..80320b8603fc6692cc5f10426d24f33b5ce0acfa 100644 (file)
@@ -532,6 +532,7 @@ struct queue_properties {
 enum mqd_update_flag {
        UPDATE_FLAG_DBG_WA_ENABLE = 1,
        UPDATE_FLAG_DBG_WA_DISABLE = 2,
+       UPDATE_FLAG_IS_GWS = 4, /* quirk for gfx9 IP */
 };
 
 struct mqd_update_info {
index 43eff221eae58ca008e2e2e92aec09eb749157d7..4858112f9a53b7e491186e0efa0e70dbb92ee47a 100644 (file)
@@ -95,6 +95,7 @@ void kfd_process_dequeue_from_device(struct kfd_process_device *pdd)
 int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid,
                        void *gws)
 {
+       struct mqd_update_info minfo = {0};
        struct kfd_node *dev = NULL;
        struct process_queue_node *pqn;
        struct kfd_process_device *pdd;
@@ -146,9 +147,10 @@ int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid,
        }
 
        pdd->qpd.num_gws = gws ? dev->adev->gds.gws_size : 0;
+       minfo.update_flag = gws ? UPDATE_FLAG_IS_GWS : 0;
 
        return pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
-                                                       pqn->q, NULL);
+                                                       pqn->q, &minfo);
 }
 
 void kfd_process_dequeue_from_all_devices(struct kfd_process *p)
index e5f7c92eebcbbfa6a1fda115ca2b599cab48e4e8..6ed2ec381aaa320ed1514038a1b6b10c44843019 100644 (file)
@@ -1638,12 +1638,10 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
                else
                        mode = UNKNOWN_MEMORY_PARTITION_MODE;
 
-               if (pcache->cache_level == 2)
-                       pcache->cache_size = pcache_info[cache_type].cache_size * num_xcc;
-               else if (mode)
-                       pcache->cache_size = pcache_info[cache_type].cache_size / mode;
-               else
-                       pcache->cache_size = pcache_info[cache_type].cache_size;
+               pcache->cache_size = pcache_info[cache_type].cache_size;
+               /* Partition mode only affects L3 cache size */
+               if (mode && pcache->cache_level == 3)
+                       pcache->cache_size /= mode;
 
                if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_DATA_CACHE)
                        pcache->cache_type |= HSA_CACHE_TYPE_DATA;
index d292f290cd6ebbfe4a2174923470a2f60e1eadc7..cf875751971feea51531ffd8580ca54fdca5287d 100644 (file)
@@ -1956,7 +1956,7 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
                                      &adev->dm.dmub_bo_gpu_addr,
                                      &adev->dm.dmub_bo_cpu_addr);
 
-       if (adev->dm.hpd_rx_offload_wq) {
+       if (adev->dm.hpd_rx_offload_wq && adev->dm.dc) {
                for (i = 0; i < adev->dm.dc->caps.max_links; i++) {
                        if (adev->dm.hpd_rx_offload_wq[i].wq) {
                                destroy_workqueue(adev->dm.hpd_rx_offload_wq[i].wq);
@@ -5219,6 +5219,7 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
                                struct drm_plane_state *new_plane_state,
                                struct drm_crtc_state *crtc_state,
                                struct dc_flip_addrs *flip_addrs,
+                               bool is_psr_su,
                                bool *dirty_regions_changed)
 {
        struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
@@ -5243,6 +5244,10 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
        num_clips = drm_plane_get_damage_clips_count(new_plane_state);
        clips = drm_plane_get_damage_clips(new_plane_state);
 
+       if (num_clips && (!amdgpu_damage_clips || (amdgpu_damage_clips < 0 &&
+                                                  is_psr_su)))
+               goto ffu;
+
        if (!dm_crtc_state->mpo_requested) {
                if (!num_clips || num_clips > DC_MAX_DIRTY_RECTS)
                        goto ffu;
@@ -6194,7 +6199,9 @@ create_stream_for_sink(struct drm_connector *connector,
                if (recalculate_timing) {
                        freesync_mode = get_highest_refresh_rate_mode(aconnector, false);
                        drm_mode_copy(&saved_mode, &mode);
+                       saved_mode.picture_aspect_ratio = mode.picture_aspect_ratio;
                        drm_mode_copy(&mode, freesync_mode);
+                       mode.picture_aspect_ratio = saved_mode.picture_aspect_ratio;
                } else {
                        decide_crtc_timing_for_drm_display_mode(
                                        &mode, preferred_mode, scale);
@@ -8298,6 +8305,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                        fill_dc_dirty_rects(plane, old_plane_state,
                                            new_plane_state, new_crtc_state,
                                            &bundle->flip_addrs[planes_count],
+                                           acrtc_state->stream->link->psr_settings.psr_version ==
+                                           DC_PSR_VERSION_SU_1,
                                            &dirty_rects_changed);
 
                        /*
@@ -10731,11 +10740,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                        goto fail;
                }
 
-               ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
-               if (ret) {
-                       DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
-                       ret = -EINVAL;
-                       goto fail;
+               if (dc_resource_is_dsc_encoding_supported(dc)) {
+                       ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
+                       if (ret) {
+                               DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
+                               ret = -EINVAL;
+                               goto fail;
+                       }
                }
 
                ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context, vars);
index f2dfa96f9ef5d9e4805fdbf592cac078efa391a5..39530b2ea4957cc0a6718f322158e101f15431d0 100644 (file)
@@ -94,7 +94,7 @@ static void calculate_bandwidth(
        const uint32_t s_high = 7;
        const uint32_t dmif_chunk_buff_margin = 1;
 
-       uint32_t max_chunks_fbc_mode;
+       uint32_t max_chunks_fbc_mode = 0;
        int32_t num_cursor_lines;
 
        int32_t i, j, k;
index 960c4b4f6ddf3670156abd99cc0a02aeb176c7dc..05f392501c0ae3572250061b31defef7cde51fb5 100644 (file)
@@ -1850,19 +1850,21 @@ static enum bp_result get_firmware_info_v3_2(
                /* Vega12 */
                smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2,
                                                        DATA_TABLES(smu_info));
-               DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage);
                if (!smu_info_v3_2)
                        return BP_RESULT_BADBIOSTABLE;
 
+               DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage);
+
                info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10;
        } else if (revision.minor == 3) {
                /* Vega20 */
                smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3,
                                                        DATA_TABLES(smu_info));
-               DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage);
                if (!smu_info_v3_3)
                        return BP_RESULT_BADBIOSTABLE;
 
+               DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage);
+
                info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10;
        }
 
@@ -2422,10 +2424,11 @@ static enum bp_result get_integrated_info_v11(
        info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,
                                        DATA_TABLES(integratedsysteminfo));
 
-       DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);
        if (info_v11 == NULL)
                return BP_RESULT_BADBIOSTABLE;
 
+       DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);
+
        info->gpu_cap_info =
        le32_to_cpu(info_v11->gpucapinfo);
        /*
@@ -2637,11 +2640,12 @@ static enum bp_result get_integrated_info_v2_1(
 
        info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,
                                        DATA_TABLES(integratedsysteminfo));
-       DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);
 
        if (info_v2_1 == NULL)
                return BP_RESULT_BADBIOSTABLE;
 
+       DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);
+
        info->gpu_cap_info =
        le32_to_cpu(info_v2_1->gpucapinfo);
        /*
@@ -2799,11 +2803,11 @@ static enum bp_result get_integrated_info_v2_2(
        info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,
                                        DATA_TABLES(integratedsysteminfo));
 
-       DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);
-
        if (info_v2_2 == NULL)
                return BP_RESULT_BADBIOSTABLE;
 
+       DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);
+
        info->gpu_cap_info =
        le32_to_cpu(info_v2_2->gpucapinfo);
        /*
index a5489fe6875f453149d622d59e9b6417b4db616c..aa9fd1dc550a5e8b2142cfb10db96f4779bdc788 100644 (file)
@@ -546,6 +546,8 @@ static unsigned int find_dcfclk_for_voltage(const struct vg_dpm_clocks *clock_ta
        int i;
 
        for (i = 0; i < VG_NUM_SOC_VOLTAGE_LEVELS; i++) {
+               if (i >= VG_NUM_DCFCLK_DPM_LEVELS)
+                       break;
                if (clock_table->SocVoltage[i] == voltage)
                        return clock_table->DcfClocks[i];
        }
index 14cec1c7b718c4ab48fbd9588f4b6465c13897cd..e648902592358ff08ca3a536d9f0abe56bfe5e34 100644 (file)
@@ -655,10 +655,13 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk
        struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1];
        uint32_t max_fclk = 0, min_pstate = 0, max_dispclk = 0, max_dppclk = 0;
        uint32_t max_pstate = 0, max_dram_speed_mts = 0, min_dram_speed_mts = 0;
+       uint32_t num_memps, num_fclk, num_dcfclk;
        int i;
 
        /* Determine min/max p-state values. */
-       for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
+       num_memps = (clock_table->NumMemPstatesEnabled > NUM_MEM_PSTATE_LEVELS) ? NUM_MEM_PSTATE_LEVELS :
+               clock_table->NumMemPstatesEnabled;
+       for (i = 0; i < num_memps; i++) {
                uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]);
 
                if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts > max_dram_speed_mts) {
@@ -670,7 +673,7 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk
        min_dram_speed_mts = max_dram_speed_mts;
        min_pstate = max_pstate;
 
-       for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
+       for (i = 0; i < num_memps; i++) {
                uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]);
 
                if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts < min_dram_speed_mts) {
@@ -699,9 +702,13 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk
        /* Base the clock table on dcfclk, need at least one entry regardless of pmfw table */
        ASSERT(clock_table->NumDcfClkLevelsEnabled > 0);
 
-       max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq, clock_table->NumFclkLevelsEnabled);
+       num_fclk = (clock_table->NumFclkLevelsEnabled > NUM_FCLK_DPM_LEVELS) ? NUM_FCLK_DPM_LEVELS :
+               clock_table->NumFclkLevelsEnabled;
+       max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq, num_fclk);
 
-       for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) {
+       num_dcfclk = (clock_table->NumFclkLevelsEnabled > NUM_DCFCLK_DPM_LEVELS) ? NUM_DCFCLK_DPM_LEVELS :
+               clock_table->NumDcfClkLevelsEnabled;
+       for (i = 0; i < num_dcfclk; i++) {
                int j;
 
                /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */
index aa7c02ba948e9ce63aa84eb7518f9c73c80d107a..2c424e435962d4ddd73648aeb3b531ad1bd7aa92 100644 (file)
@@ -3817,7 +3817,9 @@ static void commit_planes_for_stream(struct dc *dc,
                 * programming has completed (we turn on phantom OTG in order
                 * to complete the plane disable for phantom pipes).
                 */
-               dc->hwss.apply_ctx_to_hw(dc, context);
+
+               if (dc->hwss.disable_phantom_streams)
+                       dc->hwss.disable_phantom_streams(dc, context);
        }
 
        if (update_type != UPDATE_TYPE_FAST)
index 88c6436b28b69ca7f4791bdc47404cd5f73a5f83..180ac47868c22a68c1af47096db95ecf6b11994c 100644 (file)
@@ -291,11 +291,14 @@ void dc_state_destruct(struct dc_state *state)
                dc_stream_release(state->phantom_streams[i]);
                state->phantom_streams[i] = NULL;
        }
+       state->phantom_stream_count = 0;
 
        for (i = 0; i < state->phantom_plane_count; i++) {
                dc_plane_state_release(state->phantom_planes[i]);
                state->phantom_planes[i] = NULL;
        }
+       state->phantom_plane_count = 0;
+
        state->stream_mask = 0;
        memset(&state->res_ctx, 0, sizeof(state->res_ctx));
        memset(&state->pp_display_cfg, 0, sizeof(state->pp_display_cfg));
index e43f77c11c00825aad64ada6ddfb4b0bdce23aff..5f97a868ada34734d99a6a35a329d9c3cd3c5ac2 100644 (file)
@@ -56,16 +56,13 @@ static void dpp3_enable_cm_block(
 
 static enum dc_lut_mode dpp30_get_gamcor_current(struct dpp *dpp_base)
 {
-       enum dc_lut_mode mode;
+       enum dc_lut_mode mode = LUT_BYPASS;
        uint32_t state_mode;
        uint32_t lut_mode;
        struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
 
        REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, &state_mode);
 
-       if (state_mode == 0)
-               mode = LUT_BYPASS;
-
        if (state_mode == 2) {//Programmable RAM LUT
                REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT_CURRENT, &lut_mode);
                if (lut_mode == 0)
index 6042a5a6a44f8c32187b2bea702892572f08ec57..59ade76ffb18d56f26a6b329b850462150214c04 100644 (file)
@@ -72,11 +72,11 @@ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn10/dcn10_fpu.o := $(dml_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags) $(frame_warn_flag)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags) $(frame_warn_flag)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags) $(frame_warn_flag)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(frame_warn_flag)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
index dd781a20692ee68847aadccea38fecc69a2e3683..a0a65e0991041d90904c516c7279c5b8aa76967c 100644 (file)
@@ -1288,7 +1288,7 @@ static bool update_pipes_with_split_flags(struct dc *dc, struct dc_state *contex
        return updated;
 }
 
-static bool should_allow_odm_power_optimization(struct dc *dc,
+static bool should_apply_odm_power_optimization(struct dc *dc,
                struct dc_state *context, struct vba_vars_st *v, int *split,
                bool *merge)
 {
@@ -1392,9 +1392,12 @@ static void try_odm_power_optimization_and_revalidate(
 {
        int i;
        unsigned int new_vlevel;
+       unsigned int cur_policy[MAX_PIPES];
 
-       for (i = 0; i < pipe_cnt; i++)
+       for (i = 0; i < pipe_cnt; i++) {
+               cur_policy[i] = pipes[i].pipe.dest.odm_combine_policy;
                pipes[i].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
+       }
 
        new_vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
 
@@ -1403,6 +1406,9 @@ static void try_odm_power_optimization_and_revalidate(
                memset(merge, 0, MAX_PIPES * sizeof(bool));
                *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, new_vlevel, split, merge);
                context->bw_ctx.dml.vba.VoltageLevel = *vlevel;
+       } else {
+               for (i = 0; i < pipe_cnt; i++)
+                       pipes[i].pipe.dest.odm_combine_policy = cur_policy[i];
        }
 }
 
@@ -1580,7 +1586,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
                }
        }
 
-       if (should_allow_odm_power_optimization(dc, context, vba, split, merge))
+       if (should_apply_odm_power_optimization(dc, context, vba, split, merge))
                try_odm_power_optimization_and_revalidate(
                                dc, context, pipes, split, merge, vlevel, *pipe_cnt);
 
@@ -2209,7 +2215,8 @@ bool dcn32_internal_validate_bw(struct dc *dc,
                int i;
 
                pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
-               dcn32_update_dml_pipes_odm_policy_based_on_context(dc, context, pipes);
+               if (!dc->config.enable_windowed_mpo_odm)
+                       dcn32_update_dml_pipes_odm_policy_based_on_context(dc, context, pipes);
 
                /* repopulate_pipes = 1 means the pipes were either split or merged. In this case
                 * we have to re-calculate the DET allocation and run through DML once more to
@@ -2753,7 +2760,7 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk
        struct _vcs_dpi_voltage_scaling_st entry = {0};
        struct clk_limit_table_entry max_clk_data = {0};
 
-       unsigned int min_dcfclk_mhz = 399, min_fclk_mhz = 599;
+       unsigned int min_dcfclk_mhz = 199, min_fclk_mhz = 299;
 
        static const unsigned int num_dcfclk_stas = 5;
        unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {199, 615, 906, 1324, 1564};
index 2352428bcea3cab551aef88fe8bc781c443f6914..01493c49bd7a084b1748bb786c56106858709dcc 100644 (file)
@@ -1476,7 +1476,7 @@ static enum dc_status dce110_enable_stream_timing(
        return DC_OK;
 }
 
-static enum dc_status apply_single_controller_ctx_to_hw(
+enum dc_status dce110_apply_single_controller_ctx_to_hw(
                struct pipe_ctx *pipe_ctx,
                struct dc_state *context,
                struct dc *dc)
@@ -2302,7 +2302,7 @@ enum dc_status dce110_apply_ctx_to_hw(
                if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe)
                        continue;
 
-               status = apply_single_controller_ctx_to_hw(
+               status = dce110_apply_single_controller_ctx_to_hw(
                                pipe_ctx,
                                context,
                                dc);
index 08028a1779ae819282ab2394de57c4b8f266a9f3..ed3cc3648e8e23f8d076b92e10a23791253f9662 100644 (file)
@@ -39,6 +39,10 @@ enum dc_status dce110_apply_ctx_to_hw(
                struct dc *dc,
                struct dc_state *context);
 
+enum dc_status dce110_apply_single_controller_ctx_to_hw(
+               struct pipe_ctx *pipe_ctx,
+               struct dc_state *context,
+               struct dc *dc);
 
 void dce110_enable_stream(struct pipe_ctx *pipe_ctx);
 
index 4853ecac53f91f90a774192236e2d74ba6779c08..931ac8ed7069d7bdcd3ca2f0c35f5e5f04552827 100644 (file)
@@ -2561,7 +2561,7 @@ void dcn20_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx)
                tg->funcs->setup_vertical_interrupt2(tg, start_line);
 }
 
-static void dcn20_reset_back_end_for_pipe(
+void dcn20_reset_back_end_for_pipe(
                struct dc *dc,
                struct pipe_ctx *pipe_ctx,
                struct dc_state *context)
index b94c85340abff7c02f3ec59025b04c8417d77bd6..d950b3e54ec2c7d35fb1c70a53094f0543c17b97 100644 (file)
@@ -84,6 +84,10 @@ enum dc_status dcn20_enable_stream_timing(
 void dcn20_disable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx);
 void dcn20_enable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx);
 void dcn20_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx);
+void dcn20_reset_back_end_for_pipe(
+               struct dc *dc,
+               struct pipe_ctx *pipe_ctx,
+               struct dc_state *context);
 void dcn20_init_blank(
                struct dc *dc,
                struct timing_generator *tg);
index 8e88dcaf88f5b2b709a95abf9e0673390e27daa5..7252f5f781f0d7869e147846bc1eb44f09e63593 100644 (file)
@@ -206,28 +206,32 @@ void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
 void dcn21_set_pipe(struct pipe_ctx *pipe_ctx)
 {
        struct abm *abm = pipe_ctx->stream_res.abm;
-       uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
+       struct timing_generator *tg = pipe_ctx->stream_res.tg;
        struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
        struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu;
+       uint32_t otg_inst;
+
+       if (!abm || !tg || !panel_cntl)
+               return;
+
+       otg_inst = tg->inst;
 
        if (dmcu) {
                dce110_set_pipe(pipe_ctx);
                return;
        }
 
-       if (abm && panel_cntl) {
-               if (abm->funcs && abm->funcs->set_pipe_ex) {
-                       abm->funcs->set_pipe_ex(abm,
+       if (abm->funcs && abm->funcs->set_pipe_ex) {
+               abm->funcs->set_pipe_ex(abm,
                                        otg_inst,
                                        SET_ABM_PIPE_NORMAL,
                                        panel_cntl->inst,
                                        panel_cntl->pwrseq_inst);
-               } else {
-                               dmub_abm_set_pipe(abm, otg_inst,
-                                               SET_ABM_PIPE_NORMAL,
-                                               panel_cntl->inst,
-                                               panel_cntl->pwrseq_inst);
-               }
+       } else {
+               dmub_abm_set_pipe(abm, otg_inst,
+                                 SET_ABM_PIPE_NORMAL,
+                                 panel_cntl->inst,
+                                 panel_cntl->pwrseq_inst);
        }
 }
 
@@ -237,34 +241,35 @@ bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
 {
        struct dc_context *dc = pipe_ctx->stream->ctx;
        struct abm *abm = pipe_ctx->stream_res.abm;
+       struct timing_generator *tg = pipe_ctx->stream_res.tg;
        struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
+       uint32_t otg_inst;
+
+       if (!abm || !tg || !panel_cntl)
+               return false;
+
+       otg_inst = tg->inst;
 
        if (dc->dc->res_pool->dmcu) {
                dce110_set_backlight_level(pipe_ctx, backlight_pwm_u16_16, frame_ramp);
                return true;
        }
 
-       if (abm != NULL) {
-               uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
-
-               if (abm && panel_cntl) {
-                       if (abm->funcs && abm->funcs->set_pipe_ex) {
-                               abm->funcs->set_pipe_ex(abm,
-                                               otg_inst,
-                                               SET_ABM_PIPE_NORMAL,
-                                               panel_cntl->inst,
-                                               panel_cntl->pwrseq_inst);
-                       } else {
-                                       dmub_abm_set_pipe(abm,
-                                                       otg_inst,
-                                                       SET_ABM_PIPE_NORMAL,
-                                                       panel_cntl->inst,
-                                                       panel_cntl->pwrseq_inst);
-                       }
-               }
+       if (abm->funcs && abm->funcs->set_pipe_ex) {
+               abm->funcs->set_pipe_ex(abm,
+                                       otg_inst,
+                                       SET_ABM_PIPE_NORMAL,
+                                       panel_cntl->inst,
+                                       panel_cntl->pwrseq_inst);
+       } else {
+               dmub_abm_set_pipe(abm,
+                                 otg_inst,
+                                 SET_ABM_PIPE_NORMAL,
+                                 panel_cntl->inst,
+                                 panel_cntl->pwrseq_inst);
        }
 
-       if (abm && abm->funcs && abm->funcs->set_backlight_level_pwm)
+       if (abm->funcs && abm->funcs->set_backlight_level_pwm)
                abm->funcs->set_backlight_level_pwm(abm, backlight_pwm_u16_16,
                        frame_ramp, 0, panel_cntl->inst);
        else
index 6c9299c7683df19b3c444b865d297182d91ae7b3..aa36d7a56ca8c3b6f3cd47e67455ba67549bf73b 100644 (file)
@@ -1474,9 +1474,44 @@ void dcn32_update_dsc_pg(struct dc *dc,
        }
 }
 
+void dcn32_disable_phantom_streams(struct dc *dc, struct dc_state *context)
+{
+       struct dce_hwseq *hws = dc->hwseq;
+       int i;
+
+       for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
+               struct pipe_ctx *pipe_ctx_old =
+                       &dc->current_state->res_ctx.pipe_ctx[i];
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               if (!pipe_ctx_old->stream)
+                       continue;
+
+               if (dc_state_get_pipe_subvp_type(dc->current_state, pipe_ctx_old) != SUBVP_PHANTOM)
+                       continue;
+
+               if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe)
+                       continue;
+
+               if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx) ||
+                               (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM)) {
+                       struct clock_source *old_clk = pipe_ctx_old->clock_source;
+
+                       if (hws->funcs.reset_back_end_for_pipe)
+                               hws->funcs.reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
+                       if (hws->funcs.enable_stream_gating)
+                               hws->funcs.enable_stream_gating(dc, pipe_ctx_old);
+                       if (old_clk)
+                               old_clk->funcs->cs_power_down(old_clk);
+               }
+       }
+}
+
 void dcn32_enable_phantom_streams(struct dc *dc, struct dc_state *context)
 {
        unsigned int i;
+       enum dc_status status = DC_OK;
+       struct dce_hwseq *hws = dc->hwseq;
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
@@ -1497,16 +1532,39 @@ void dcn32_enable_phantom_streams(struct dc *dc, struct dc_state *context)
                }
        }
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
-
-               if (new_pipe->stream && dc_state_get_pipe_subvp_type(context, new_pipe) == SUBVP_PHANTOM) {
-                       // If old context or new context has phantom pipes, apply
-                       // the phantom timings now. We can't change the phantom
-                       // pipe configuration safely without driver acquiring
-                       // the DMCUB lock first.
-                       dc->hwss.apply_ctx_to_hw(dc, context);
-                       break;
+               struct pipe_ctx *pipe_ctx_old =
+                                       &dc->current_state->res_ctx.pipe_ctx[i];
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               if (pipe_ctx->stream == NULL)
+                       continue;
+
+               if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM)
+                       continue;
+
+               if (pipe_ctx->stream == pipe_ctx_old->stream &&
+                       pipe_ctx->stream->link->link_state_valid) {
+                       continue;
                }
+
+               if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
+                       continue;
+
+               if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe)
+                       continue;
+
+               if (hws->funcs.apply_single_controller_ctx_to_hw)
+                       status = hws->funcs.apply_single_controller_ctx_to_hw(
+                                       pipe_ctx,
+                                       context,
+                                       dc);
+
+               ASSERT(status == DC_OK);
+
+#ifdef CONFIG_DRM_AMD_DC_FP
+               if (hws->funcs.resync_fifo_dccg_dio)
+                       hws->funcs.resync_fifo_dccg_dio(hws, dc, context);
+#endif
        }
 }
 
index cecf7f0f567190b257cf81e5f756b5a916eba09c..069e20bc87c0a75af028168253219fc9343b1af3 100644 (file)
@@ -111,6 +111,8 @@ void dcn32_update_dsc_pg(struct dc *dc,
 
 void dcn32_enable_phantom_streams(struct dc *dc, struct dc_state *context);
 
+void dcn32_disable_phantom_streams(struct dc *dc, struct dc_state *context);
+
 void dcn32_init_blank(
                struct dc *dc,
                struct timing_generator *tg);
index 427cfc8c24a4b7ed4cee1f0b6955cbe371797219..e8ac94a005b83a78533646aae0a36ca132eb8a75 100644 (file)
@@ -109,6 +109,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
        .get_dcc_en_bits = dcn10_get_dcc_en_bits,
        .commit_subvp_config = dcn32_commit_subvp_config,
        .enable_phantom_streams = dcn32_enable_phantom_streams,
+       .disable_phantom_streams = dcn32_disable_phantom_streams,
        .subvp_pipe_control_lock = dcn32_subvp_pipe_control_lock,
        .update_visual_confirm_color = dcn10_update_visual_confirm_color,
        .subvp_pipe_control_lock_fast = dcn32_subvp_pipe_control_lock_fast,
@@ -159,6 +160,8 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
        .set_pixels_per_cycle = dcn32_set_pixels_per_cycle,
        .resync_fifo_dccg_dio = dcn32_resync_fifo_dccg_dio,
        .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy,
+       .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw,
+       .reset_back_end_for_pipe = dcn20_reset_back_end_for_pipe,
 };
 
 void dcn32_hw_sequencer_init_functions(struct dc *dc)
index a54399383318145b8bc72fc85e646bf546588609..64ca7c66509b79bc2cfe50806cc37e8953468239 100644 (file)
@@ -379,6 +379,7 @@ struct hw_sequencer_funcs {
                        struct dc_cursor_attributes *cursor_attr);
        void (*commit_subvp_config)(struct dc *dc, struct dc_state *context);
        void (*enable_phantom_streams)(struct dc *dc, struct dc_state *context);
+       void (*disable_phantom_streams)(struct dc *dc, struct dc_state *context);
        void (*subvp_pipe_control_lock)(struct dc *dc,
                        struct dc_state *context,
                        bool lock,
index 6137cf09aa54d25750246e86583c5938e557501b..b3c62a82cb1cf10fddad52dcf85b7e02de87ee35 100644 (file)
@@ -165,8 +165,15 @@ struct hwseq_private_funcs {
        void (*set_pixels_per_cycle)(struct pipe_ctx *pipe_ctx);
        void (*resync_fifo_dccg_dio)(struct dce_hwseq *hws, struct dc *dc,
                        struct dc_state *context);
+       enum dc_status (*apply_single_controller_ctx_to_hw)(
+                       struct pipe_ctx *pipe_ctx,
+                       struct dc_state *context,
+                       struct dc *dc);
        bool (*is_dp_dig_pixel_rate_div_policy)(struct pipe_ctx *pipe_ctx);
 #endif
+       void (*reset_back_end_for_pipe)(struct dc *dc,
+                       struct pipe_ctx *pipe_ctx,
+                       struct dc_state *context);
 };
 
 struct dce_hwseq {
index c958ef37b78a667b1bb9bfb26827ae3e45053715..77a60aa9f27bbfdfa8a652306e2366dc0eca4345 100644 (file)
@@ -427,22 +427,18 @@ struct pipe_ctx *resource_get_primary_dpp_pipe(const struct pipe_ctx *dpp_pipe);
 int resource_get_mpc_slice_index(const struct pipe_ctx *dpp_pipe);
 
 /*
- * Get number of MPC "cuts" of the plane associated with the pipe. MPC slice
- * count is equal to MPC splits + 1. For example if a plane is cut 3 times, it
- * will have 4 pieces of slice.
- * return - 0 if pipe is not used for a plane with MPCC combine. otherwise
- * the number of MPC "cuts" for the plane.
+ * Get the number of MPC slices associated with the pipe.
+ * The function returns 0 if the pipe is not associated with an MPC combine
+ * pipe topology.
  */
-int resource_get_mpc_slice_count(const struct pipe_ctx *opp_head);
+int resource_get_mpc_slice_count(const struct pipe_ctx *pipe);
 
 /*
- * Get number of ODM "cuts" of the timing associated with the pipe. ODM slice
- * count is equal to ODM splits + 1. For example if a timing is cut 3 times, it
- * will have 4 pieces of slice.
- * return - 0 if pipe is not used for ODM combine. otherwise
- * the number of ODM "cuts" for the timing.
+ * Get the number of ODM slices associated with the pipe.
+ * The function returns 0 if the pipe is not associated with an ODM combine
+ * pipe topology.
  */
-int resource_get_odm_slice_count(const struct pipe_ctx *otg_master);
+int resource_get_odm_slice_count(const struct pipe_ctx *pipe);
 
 /* Get the ODM slice index counting from 0 from left most slice */
 int resource_get_odm_slice_index(const struct pipe_ctx *opp_head);
index 8fe66c3678508d9aee6779fa25cd6128e1f30832..5b0bc7f6a188ccd6b304a369be0bdfe43b91f76a 100644 (file)
@@ -361,7 +361,7 @@ bool link_validate_dpia_bandwidth(const struct dc_stream_state *stream, const un
        struct dc_link *dpia_link[MAX_DPIA_NUM] = {0};
        int num_dpias = 0;
 
-       for (uint8_t i = 0; i < num_streams; ++i) {
+       for (unsigned int i = 0; i < num_streams; ++i) {
                if (stream[i].signal == SIGNAL_TYPE_DISPLAY_PORT) {
                        /* new dpia sst stream, check whether it exceeds max dpia */
                        if (num_dpias >= MAX_DPIA_NUM)
index 5a0b0451895690d184ec00c56873f0d1acad6864..16a62e01871224495cd771c4042f04d3be85e04d 100644 (file)
@@ -517,6 +517,7 @@ enum link_training_result dp_check_link_loss_status(
 {
        enum link_training_result status = LINK_TRAINING_SUCCESS;
        union lane_status lane_status;
+       union lane_align_status_updated dpcd_lane_status_updated;
        uint8_t dpcd_buf[6] = {0};
        uint32_t lane;
 
@@ -532,10 +533,12 @@ enum link_training_result dp_check_link_loss_status(
                 * check lanes status
                 */
                lane_status.raw = dp_get_nibble_at_index(&dpcd_buf[2], lane);
+               dpcd_lane_status_updated.raw = dpcd_buf[4];
 
                if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
                        !lane_status.bits.CR_DONE_0 ||
-                       !lane_status.bits.SYMBOL_LOCKED_0) {
+                       !lane_status.bits.SYMBOL_LOCKED_0 ||
+                       !dp_is_interlane_aligned(dpcd_lane_status_updated)) {
                        /* if one of the channel equalization, clock
                         * recovery or symbol lock is dropped
                         * consider it as (link has been
index e8dda44b23cb29aa3ec2686b6656bd044c194606..5d36bab0029ca54a03aaef4fc83ff99e59550e5a 100644 (file)
@@ -619,7 +619,7 @@ static enum link_training_result dpia_training_eq_non_transparent(
        uint32_t retries_eq = 0;
        enum dc_status status;
        enum dc_dp_training_pattern tr_pattern;
-       uint32_t wait_time_microsec;
+       uint32_t wait_time_microsec = 0;
        enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
        union lane_align_status_updated dpcd_lane_status_updated = {0};
        union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
index 511ff6b5b9856776ea834393e4a7bfcaa90ca49f..7538b548c5725177b12e2d169acc681c31174797 100644 (file)
@@ -999,7 +999,7 @@ static struct stream_encoder *dcn301_stream_encoder_create(enum engine_id eng_id
        vpg = dcn301_vpg_create(ctx, vpg_inst);
        afmt = dcn301_afmt_create(ctx, afmt_inst);
 
-       if (!enc1 || !vpg || !afmt) {
+       if (!enc1 || !vpg || !afmt || eng_id >= ARRAY_SIZE(stream_enc_regs)) {
                kfree(enc1);
                kfree(vpg);
                kfree(afmt);
index c4d71e7f18af47ba47dbc89e1a9098a0a4eade04..6f10052caeef02c3448307c4c81aef805e68e95b 100644 (file)
@@ -1829,7 +1829,21 @@ int dcn32_populate_dml_pipes_from_context(
                dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt);
                DC_FP_END();
                pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
-               pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
+               if (dc->config.enable_windowed_mpo_odm &&
+                               dc->debug.enable_single_display_2to1_odm_policy) {
+                       switch (resource_get_odm_slice_count(pipe)) {
+                       case 2:
+                               pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
+                               break;
+                       case 4:
+                               pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_4to1;
+                               break;
+                       default:
+                               pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
+                       }
+               } else {
+                       pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
+               }
                pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet
                pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
                pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19;
index 761ec989187568730fdd8cd51cd1802fa657be9c..5fdcda8f86026d94697a069ed53a83752a0ebdee 100644 (file)
@@ -780,8 +780,8 @@ static const struct dc_debug_options debug_defaults_drv = {
        .disable_z10 = false,
        .ignore_pg = true,
        .psp_disabled_wa = true,
-       .ips2_eval_delay_us = 200,
-       .ips2_entry_delay_us = 400,
+       .ips2_eval_delay_us = 2000,
+       .ips2_entry_delay_us = 800,
        .static_screen_wait_frames = 2,
 };
 
@@ -2130,6 +2130,7 @@ static bool dcn35_resource_construct(
        dc->dml2_options.dcn_pipe_count = pool->base.pipe_count;
        dc->dml2_options.use_native_pstate_optimization = true;
        dc->dml2_options.use_native_soc_bb_construction = true;
+       dc->dml2_options.minimize_dispclk_using_odm = false;
        if (dc->config.EnableMinDispClkODM)
                dc->dml2_options.minimize_dispclk_using_odm = true;
        dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm;
index f57e6d74fb0e039a710b9bd8161a8e8e25d5888b..c1a99bf4dffd1d221d9ca9e57d303d415acef00f 100644 (file)
@@ -539,6 +539,12 @@ static int __alloc_range(struct drm_buddy *mm,
        } while (1);
 
        list_splice_tail(&allocated, blocks);
+
+       if (total_allocated < size) {
+               err = -ENOSPC;
+               goto err_free;
+       }
+
        return 0;
 
 err_undo:
index cb90e70d85e862a495f2e8691813161a93b7a030..65f9f66933bba2785fc3b64f7040e676c2afd352 100644 (file)
@@ -904,6 +904,7 @@ out:
        connector_set = NULL;
        fb = NULL;
        mode = NULL;
+       num_connectors = 0;
 
        DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
 
index 834a5e28abbe5959cc6da2933904c4feb4c7b00d..7352bde299d54767fecb34232cb5941a01d6ea88 100644 (file)
@@ -820,7 +820,7 @@ struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
        if (max_segment == 0)
                max_segment = UINT_MAX;
        err = sg_alloc_table_from_pages_segment(sg, pages, nr_pages, 0,
-                                               nr_pages << PAGE_SHIFT,
+                                               (unsigned long)nr_pages << PAGE_SHIFT,
                                                max_segment, GFP_KERNEL);
        if (err) {
                kfree(sg);
index b5d6e3352071f5c3765f074200180bd6dfc7685c..3089029abba481828522070dc0063eaa79251bf9 100644 (file)
@@ -140,7 +140,7 @@ config DRM_I915_GVT_KVMGT
 
          Note that this driver only supports newer device from Broadwell on.
          For further information and setup guide, you can visit:
-         http://01.org/igvt-g.
+         https://github.com/intel/gvt-linux/wiki.
 
          If in doubt, say "N".
 
index f5ef95da55346ff14cc6b102c27e78e8960cec65..ae647d03af25cd48a3151b362c5ed1e752bdba60 100644 (file)
@@ -2355,6 +2355,9 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
        limits->min_rate = intel_dp_common_rate(intel_dp, 0);
        limits->max_rate = intel_dp_max_link_rate(intel_dp);
 
+       /* FIXME 128b/132b SST support missing */
+       limits->max_rate = min(limits->max_rate, 810000);
+
        limits->min_lane_count = 1;
        limits->max_lane_count = intel_dp_max_lane_count(intel_dp);
 
index 64f440fdc22b2c832a77ca7ca73cf83ecc5ba625..8b21dc8e26d525f514f74f2a647ea703b2cd2d9a 100644 (file)
@@ -51,8 +51,8 @@
 #define DSCC_PICTURE_PARAMETER_SET_0           _MMIO(0x6BA00)
 #define _DSCA_PPS_0                            0x6B200
 #define _DSCC_PPS_0                            0x6BA00
-#define DSCA_PPS(pps)                          _MMIO(_DSCA_PPS_0 + (pps) * 4)
-#define DSCC_PPS(pps)                          _MMIO(_DSCC_PPS_0 + (pps) * 4)
+#define DSCA_PPS(pps)                          _MMIO(_DSCA_PPS_0 + ((pps) < 12 ? (pps) : (pps) + 12) * 4)
+#define DSCC_PPS(pps)                          _MMIO(_DSCC_PPS_0 + ((pps) < 12 ? (pps) : (pps) + 12) * 4)
 #define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PB   0x78270
 #define _ICL_DSC1_PICTURE_PARAMETER_SET_0_PB   0x78370
 #define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PC   0x78470
index 90f6c1ece57d4478a30375df1725624b47449298..efcb00472be24779590fcce94753ab83a787f2c4 100644 (file)
@@ -2849,8 +2849,7 @@ static int handle_mmio(struct intel_gvt_mmio_table_iter *iter, u32 offset,
        for (i = start; i < end; i += 4) {
                p = intel_gvt_find_mmio_info(gvt, i);
                if (p) {
-                       WARN(1, "dup mmio definition offset %x\n",
-                               info->offset);
+                       WARN(1, "dup mmio definition offset %x\n", i);
 
                        /* We return -EEXIST here to make GVT-g load fail.
                         * So duplicated MMIO can be found as soon as
index e98b6d69a91ab70c224d67ad337926c1b69936b3..9b6d87c8b5831c14aec9bbc425a374f0721f0273 100644 (file)
@@ -41,7 +41,7 @@
  * To virtualize GPU resources GVT-g driver depends on hypervisor technology
  * e.g KVM/VFIO/mdev, Xen, etc. to provide resource access trapping capability
  * and be virtualized within GVT-g device module. More architectural design
- * doc is available on https://01.org/group/2230/documentation-list.
+ * doc is available on https://github.com/intel/gvt-linux/wiki.
  */
 
 static LIST_HEAD(intel_gvt_devices);
index c0bc924cd3025dc21939e2e75548f273a90fd620..c9c55e2ea584927ce7b3f8ffc50e7ed807f6671a 100644 (file)
@@ -1287,7 +1287,7 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
        gpu->ubwc_config.highest_bank_bit = 15;
 
        if (adreno_is_a610(gpu)) {
-               gpu->ubwc_config.highest_bank_bit = 14;
+               gpu->ubwc_config.highest_bank_bit = 13;
                gpu->ubwc_config.min_acc_len = 1;
                gpu->ubwc_config.ubwc_mode = 1;
        }
index 83380bc92a00a964479a0cbbb8dbc7a9dcd675ca..6a4b489d44e5173831d73956f1fb7a4e10809052 100644 (file)
@@ -144,10 +144,6 @@ enum dpu_enc_rc_states {
  *                     to track crtc in the disable() hook which is called
  *                     _after_ encoder_mask is cleared.
  * @connector:         If a mode is set, cached pointer to the active connector
- * @crtc_kickoff_cb:           Callback into CRTC that will flush & start
- *                             all CTL paths
- * @crtc_kickoff_cb_data:      Opaque user data given to crtc_kickoff_cb
- * @debugfs_root:              Debug file system root file node
  * @enc_lock:                  Lock around physical encoder
  *                             create/destroy/enable/disable
  * @frame_busy_mask:           Bitmask tracking which phys_enc we are still
@@ -2072,7 +2068,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
        }
 
        /* reset the merge 3D HW block */
-       if (phys_enc->hw_pp->merge_3d) {
+       if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) {
                phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
                                BLEND_3D_NONE);
                if (phys_enc->hw_ctl->ops.update_pending_flush_merge_3d)
@@ -2103,7 +2099,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
        if (phys_enc->hw_wb)
                intf_cfg.wb = phys_enc->hw_wb->idx;
 
-       if (phys_enc->hw_pp->merge_3d)
+       if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d)
                intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx;
 
        if (ctl->ops.reset_intf_cfg)
index b58a9c2ae326cab6c4799a88fe86acbab1c236f8..724537ab776dfde95c6406cf0aef1b795874b171 100644 (file)
@@ -29,7 +29,6 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
 /**
  * struct dpu_rm_requirements - Reservation requirements parameter bundle
  * @topology:  selected topology for the display
- * @hw_res:       Hardware resources required as reported by the encoders
  */
 struct dpu_rm_requirements {
        struct msm_display_topology topology;
@@ -204,6 +203,8 @@ static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top)
  * _dpu_rm_get_lm_peer - get the id of a mixer which is a peer of the primary
  * @rm: dpu resource manager handle
  * @primary_idx: index of primary mixer in rm->mixer_blks[]
+ *
+ * Returns: lm peer mixed id on success or %-EINVAL on error
  */
 static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
 {
index 77a8d9366ed7b01d46a01cf602e74eafb15d4937..fb588fde298a2de231ea5fdd8f639da156d47030 100644 (file)
@@ -135,11 +135,6 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
        tbd = dp_link_get_test_bits_depth(ctrl->link,
                        ctrl->panel->dp_mode.bpp);
 
-       if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) {
-               pr_debug("BIT_DEPTH not set. Configure default\n");
-               tbd = DP_TEST_BIT_DEPTH_8;
-       }
-
        config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT;
 
        /* Num of Lanes */
index 98427d45e9a7e3ac99a47871bbd1e0e893b2bc24..49dfac1fd1ef2158626f4a417b22e810414b76f9 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <drm/drm_print.h>
 
+#include "dp_reg.h"
 #include "dp_link.h"
 #include "dp_panel.h"
 
@@ -1082,7 +1083,7 @@ int dp_link_process_request(struct dp_link *dp_link)
 
 int dp_link_get_colorimetry_config(struct dp_link *dp_link)
 {
-       u32 cc;
+       u32 cc = DP_MISC0_COLORIMERY_CFG_LEGACY_RGB;
        struct dp_link_private *link;
 
        if (!dp_link) {
@@ -1096,10 +1097,11 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link)
         * Unless a video pattern CTS test is ongoing, use RGB_VESA
         * Only RGB_VESA and RGB_CEA supported for now
         */
-       if (dp_link_is_video_pattern_requested(link))
-               cc = link->dp_link.test_video.test_dyn_range;
-       else
-               cc = DP_TEST_DYNAMIC_RANGE_VESA;
+       if (dp_link_is_video_pattern_requested(link)) {
+               if (link->dp_link.test_video.test_dyn_range &
+                                       DP_TEST_DYNAMIC_RANGE_CEA)
+                       cc = DP_MISC0_COLORIMERY_CFG_CEA_RGB;
+       }
 
        return cc;
 }
@@ -1179,6 +1181,9 @@ void dp_link_reset_phy_params_vx_px(struct dp_link *dp_link)
 u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp)
 {
        u32 tbd;
+       struct dp_link_private *link;
+
+       link = container_of(dp_link, struct dp_link_private, dp_link);
 
        /*
         * Few simplistic rules and assumptions made here:
@@ -1196,12 +1201,13 @@ u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp)
                tbd = DP_TEST_BIT_DEPTH_10;
                break;
        default:
-               tbd = DP_TEST_BIT_DEPTH_UNKNOWN;
+               drm_dbg_dp(link->drm_dev, "bpp=%d not supported, use bpc=8\n",
+                          bpp);
+               tbd = DP_TEST_BIT_DEPTH_8;
                break;
        }
 
-       if (tbd != DP_TEST_BIT_DEPTH_UNKNOWN)
-               tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT);
+       tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT);
 
        return tbd;
 }
index ea85a691e72b5ce505822e4fce21f0cbcf0c4319..78785ed4b40c490d83396825d62a65af2fd6c9df 100644 (file)
 #define DP_MISC0_COLORIMETRY_CFG_SHIFT         (0x00000001)
 #define DP_MISC0_TEST_BITS_DEPTH_SHIFT         (0x00000005)
 
+#define DP_MISC0_COLORIMERY_CFG_LEGACY_RGB     (0)
+#define DP_MISC0_COLORIMERY_CFG_CEA_RGB                (0x04)
+
 #define REG_DP_VALID_BOUNDARY                  (0x00000030)
 #define REG_DP_VALID_BOUNDARY_2                        (0x00000034)
 
index 5f68e31a3e4e1cbeed95bfde138711c0fc9c9759..0915f3b68752e34702ae8864249d049e3b277ee2 100644 (file)
@@ -26,7 +26,7 @@ int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
 {
        void *vaddr;
 
-       vaddr = msm_gem_get_vaddr(obj);
+       vaddr = msm_gem_get_vaddr_locked(obj);
        if (IS_ERR(vaddr))
                return PTR_ERR(vaddr);
        iosys_map_set_vaddr(map, vaddr);
@@ -36,7 +36,7 @@ int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
 
 void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
 {
-       msm_gem_put_vaddr(obj);
+       msm_gem_put_vaddr_locked(obj);
 }
 
 struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
index 095390774f22b547668227ed492a6e9783b055f9..655002b21b0d5dc345283a7699d14b0e88b3e472 100644 (file)
@@ -751,12 +751,14 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
        struct msm_ringbuffer *ring = submit->ring;
        unsigned long flags;
 
-       pm_runtime_get_sync(&gpu->pdev->dev);
+       WARN_ON(!mutex_is_locked(&gpu->lock));
 
-       mutex_lock(&gpu->lock);
+       pm_runtime_get_sync(&gpu->pdev->dev);
 
        msm_gpu_hw_init(gpu);
 
+       submit->seqno = submit->hw_fence->seqno;
+
        update_sw_cntrs(gpu);
 
        /*
@@ -781,11 +783,8 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
        gpu->funcs->submit(gpu, submit);
        gpu->cur_ctx_seqno = submit->queue->ctx->seqno;
 
-       hangcheck_timer_reset(gpu);
-
-       mutex_unlock(&gpu->lock);
-
        pm_runtime_put(&gpu->pdev->dev);
+       hangcheck_timer_reset(gpu);
 }
 
 /*
index 5cc8d358cc9759307a444cd62bce83c62b3dcdb7..d5512037c38bcd7ca807aaf281dceaebdd688a4e 100644 (file)
@@ -21,6 +21,8 @@ struct msm_iommu_pagetable {
        struct msm_mmu base;
        struct msm_mmu *parent;
        struct io_pgtable_ops *pgtbl_ops;
+       const struct iommu_flush_ops *tlb;
+       struct device *iommu_dev;
        unsigned long pgsize_bitmap;    /* Bitmap of page sizes in use */
        phys_addr_t ttbr;
        u32 asid;
@@ -201,11 +203,33 @@ static const struct msm_mmu_funcs pagetable_funcs = {
 
 static void msm_iommu_tlb_flush_all(void *cookie)
 {
+       struct msm_iommu_pagetable *pagetable = cookie;
+       struct adreno_smmu_priv *adreno_smmu;
+
+       if (!pm_runtime_get_if_in_use(pagetable->iommu_dev))
+               return;
+
+       adreno_smmu = dev_get_drvdata(pagetable->parent->dev);
+
+       pagetable->tlb->tlb_flush_all((void *)adreno_smmu->cookie);
+
+       pm_runtime_put_autosuspend(pagetable->iommu_dev);
 }
 
 static void msm_iommu_tlb_flush_walk(unsigned long iova, size_t size,
                size_t granule, void *cookie)
 {
+       struct msm_iommu_pagetable *pagetable = cookie;
+       struct adreno_smmu_priv *adreno_smmu;
+
+       if (!pm_runtime_get_if_in_use(pagetable->iommu_dev))
+               return;
+
+       adreno_smmu = dev_get_drvdata(pagetable->parent->dev);
+
+       pagetable->tlb->tlb_flush_walk(iova, size, granule, (void *)adreno_smmu->cookie);
+
+       pm_runtime_put_autosuspend(pagetable->iommu_dev);
 }
 
 static void msm_iommu_tlb_add_page(struct iommu_iotlb_gather *gather,
@@ -213,7 +237,7 @@ static void msm_iommu_tlb_add_page(struct iommu_iotlb_gather *gather,
 {
 }
 
-static const struct iommu_flush_ops null_tlb_ops = {
+static const struct iommu_flush_ops tlb_ops = {
        .tlb_flush_all = msm_iommu_tlb_flush_all,
        .tlb_flush_walk = msm_iommu_tlb_flush_walk,
        .tlb_add_page = msm_iommu_tlb_add_page,
@@ -254,10 +278,10 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent)
 
        /* The incoming cfg will have the TTBR1 quirk enabled */
        ttbr0_cfg.quirks &= ~IO_PGTABLE_QUIRK_ARM_TTBR1;
-       ttbr0_cfg.tlb = &null_tlb_ops;
+       ttbr0_cfg.tlb = &tlb_ops;
 
        pagetable->pgtbl_ops = alloc_io_pgtable_ops(ARM_64_LPAE_S1,
-               &ttbr0_cfg, iommu->domain);
+               &ttbr0_cfg, pagetable);
 
        if (!pagetable->pgtbl_ops) {
                kfree(pagetable);
@@ -279,6 +303,8 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent)
 
        /* Needed later for TLB flush */
        pagetable->parent = parent;
+       pagetable->tlb = ttbr1_cfg->tlb;
+       pagetable->iommu_dev = ttbr1_cfg->iommu_dev;
        pagetable->pgsize_bitmap = ttbr0_cfg.pgsize_bitmap;
        pagetable->ttbr = ttbr0_cfg.arm_lpae_s1_cfg.ttbr;
 
index 455b2e3a0cdd4811c67fda8efccd9dd3dcf77a16..35423d10aafa90b98bb6f92c3da405940c8938ea 100644 (file)
@@ -562,6 +562,7 @@ static const struct msm_mdss_data sdm670_data = {
        .ubwc_enc_version = UBWC_2_0,
        .ubwc_dec_version = UBWC_2_0,
        .highest_bank_bit = 1,
+       .reg_bus_bw = 76800,
 };
 
 static const struct msm_mdss_data sdm845_data = {
index 4bc13f7d005ab7c643f78206d8d41d72cd779045..9d6655f96f0cebcc0c03e5b9bef6900c299f2f0d 100644 (file)
@@ -21,8 +21,6 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job)
 
        msm_fence_init(submit->hw_fence, fctx);
 
-       submit->seqno = submit->hw_fence->seqno;
-
        mutex_lock(&priv->lru.lock);
 
        for (i = 0; i < submit->nr_bos; i++) {
@@ -35,8 +33,13 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job)
 
        mutex_unlock(&priv->lru.lock);
 
+       /* TODO move submit path over to using a per-ring lock.. */
+       mutex_lock(&gpu->lock);
+
        msm_gpu_submit(gpu, submit);
 
+       mutex_unlock(&gpu->lock);
+
        return dma_fence_get(submit->hw_fence);
 }
 
index d1437c08645f90d9c745ee77405d3fa1d8d51f9d..6f5d376d8fcc1ecb6d9faa80b4b06ba4cd1b21e4 100644 (file)
@@ -9,7 +9,7 @@
 #define GSP_PAGE_SIZE  BIT(GSP_PAGE_SHIFT)
 
 struct nvkm_gsp_mem {
-       u32 size;
+       size_t size;
        void *data;
        dma_addr_t addr;
 };
index a04156ca8390ba6fea6a21e07e9eb5bba3ec7605..d1bb8151a1df565c44db55432222f09641d7b109 100644 (file)
@@ -128,12 +128,14 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
        struct nouveau_abi16_ntfy *ntfy, *temp;
 
        /* Cancel all jobs from the entity's queue. */
-       drm_sched_entity_fini(&chan->sched.entity);
+       if (chan->sched)
+               drm_sched_entity_fini(&chan->sched->entity);
 
        if (chan->chan)
                nouveau_channel_idle(chan->chan);
 
-       nouveau_sched_fini(&chan->sched);
+       if (chan->sched)
+               nouveau_sched_destroy(&chan->sched);
 
        /* cleanup notifier state */
        list_for_each_entry_safe(ntfy, temp, &chan->notifiers, head) {
@@ -337,10 +339,16 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
        if (ret)
                goto done;
 
-       ret = nouveau_sched_init(&chan->sched, drm, drm->sched_wq,
-                                chan->chan->dma.ib_max);
-       if (ret)
-               goto done;
+       /* If we're not using the VM_BIND uAPI, we don't need a scheduler.
+        *
+        * The client lock is already acquired by nouveau_abi16_get().
+        */
+       if (nouveau_cli_uvmm(cli)) {
+               ret = nouveau_sched_create(&chan->sched, drm, drm->sched_wq,
+                                          chan->chan->dma.ib_max);
+               if (ret)
+                       goto done;
+       }
 
        init->channel = chan->chan->chid;
 
index 1f5e243c0c759ef759dbba7d4f89279c90bce5d4..11c8c4a80079bbb2b658816dd42d05f68a5eaab6 100644 (file)
@@ -26,7 +26,7 @@ struct nouveau_abi16_chan {
        struct nouveau_bo *ntfy;
        struct nouveau_vma *ntfy_vma;
        struct nvkm_mm  heap;
-       struct nouveau_sched sched;
+       struct nouveau_sched *sched;
 };
 
 struct nouveau_abi16 {
index 6f6c31a9937b2fe751c6cffe429cc21a6b47a385..a947e1d5f309ae525e8087d13899f1efd1e8e73b 100644 (file)
@@ -201,7 +201,8 @@ nouveau_cli_fini(struct nouveau_cli *cli)
        WARN_ON(!list_empty(&cli->worker));
 
        usif_client_fini(cli);
-       nouveau_sched_fini(&cli->sched);
+       if (cli->sched)
+               nouveau_sched_destroy(&cli->sched);
        if (uvmm)
                nouveau_uvmm_fini(uvmm);
        nouveau_vmm_fini(&cli->svm);
@@ -311,7 +312,7 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
        cli->mem = &mems[ret];
 
        /* Don't pass in the (shared) sched_wq in order to let
-        * nouveau_sched_init() create a dedicated one for VM_BIND jobs.
+        * nouveau_sched_create() create a dedicated one for VM_BIND jobs.
         *
         * This is required to ensure that for VM_BIND jobs free_job() work and
         * run_job() work can always run concurrently and hence, free_job() work
@@ -320,7 +321,7 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
         * locks which indirectly or directly are held for allocations
         * elsewhere.
         */
-       ret = nouveau_sched_init(&cli->sched, drm, NULL, 1);
+       ret = nouveau_sched_create(&cli->sched, drm, NULL, 1);
        if (ret)
                goto done;
 
index 8a6d94c8b1631fd7ab8bbc193f35b064057a0185..e239c6bf4afa4f75d4ca30c63583af82f2ab9621 100644 (file)
@@ -98,7 +98,7 @@ struct nouveau_cli {
                bool disabled;
        } uvmm;
 
-       struct nouveau_sched sched;
+       struct nouveau_sched *sched;
 
        const struct nvif_mclass *mem;
 
index bc5d71b79ab203ff7e874c612f3ea1e7c36323de..e65c0ef23bc73d59f3066ff02ae9360253b93e6d 100644 (file)
@@ -389,7 +389,7 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
        if (ret)
                goto out;
 
-       args.sched = &chan16->sched;
+       args.sched = chan16->sched;
        args.file_priv = file_priv;
        args.chan = chan;
 
index dd98f6910f9cab7b19117186339a138277e77b78..32fa2e273965bf140a4cb2e05262b638c312cd6e 100644 (file)
@@ -398,7 +398,7 @@ static const struct drm_sched_backend_ops nouveau_sched_ops = {
        .free_job = nouveau_sched_free_job,
 };
 
-int
+static int
 nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm,
                   struct workqueue_struct *wq, u32 credit_limit)
 {
@@ -453,7 +453,30 @@ fail_wq:
        return ret;
 }
 
-void
+int
+nouveau_sched_create(struct nouveau_sched **psched, struct nouveau_drm *drm,
+                    struct workqueue_struct *wq, u32 credit_limit)
+{
+       struct nouveau_sched *sched;
+       int ret;
+
+       sched = kzalloc(sizeof(*sched), GFP_KERNEL);
+       if (!sched)
+               return -ENOMEM;
+
+       ret = nouveau_sched_init(sched, drm, wq, credit_limit);
+       if (ret) {
+               kfree(sched);
+               return ret;
+       }
+
+       *psched = sched;
+
+       return 0;
+}
+
+
+static void
 nouveau_sched_fini(struct nouveau_sched *sched)
 {
        struct drm_gpu_scheduler *drm_sched = &sched->base;
@@ -471,3 +494,14 @@ nouveau_sched_fini(struct nouveau_sched *sched)
        if (sched->wq)
                destroy_workqueue(sched->wq);
 }
+
+void
+nouveau_sched_destroy(struct nouveau_sched **psched)
+{
+       struct nouveau_sched *sched = *psched;
+
+       nouveau_sched_fini(sched);
+       kfree(sched);
+
+       *psched = NULL;
+}
index a6528f5981e6a6e8182a44e0ec3c0336302e6154..e1f01a23e6f6e84cf2700bde86e4fb5e3e013df1 100644 (file)
@@ -111,8 +111,8 @@ struct nouveau_sched {
        } job;
 };
 
-int nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm,
-                      struct workqueue_struct *wq, u32 credit_limit);
-void nouveau_sched_fini(struct nouveau_sched *sched);
+int nouveau_sched_create(struct nouveau_sched **psched, struct nouveau_drm *drm,
+                        struct workqueue_struct *wq, u32 credit_limit);
+void nouveau_sched_destroy(struct nouveau_sched **psched);
 
 #endif
index cc03e0c22ff3fec65cf6a40ae34db2af20bb349e..5e4565c5011a976d1c8057e9366d9e1da03de97a 100644 (file)
@@ -1011,7 +1011,7 @@ nouveau_svm_fault_buffer_ctor(struct nouveau_svm *svm, s32 oclass, int id)
        if (ret)
                return ret;
 
-       buffer->fault = kvcalloc(sizeof(*buffer->fault), buffer->entries, GFP_KERNEL);
+       buffer->fault = kvcalloc(buffer->entries, sizeof(*buffer->fault), GFP_KERNEL);
        if (!buffer->fault)
                return -ENOMEM;
 
index 4f223c972c6a8cb3bab7873dfa2a1c38756648b2..0a0a11dc9ec03eeba855f47ca57c1ad1c5669f54 100644 (file)
@@ -1740,7 +1740,7 @@ nouveau_uvmm_ioctl_vm_bind(struct drm_device *dev,
        if (ret)
                return ret;
 
-       args.sched = &cli->sched;
+       args.sched = cli->sched;
        args.file_priv = file_priv;
 
        ret = nouveau_uvmm_vm_bind(&args);
index 5e1fa176aac4a4b9e33562236b8b93889dae58ac..a41735ab60683f02fde33f0107a2edae89155a6e 100644 (file)
@@ -997,6 +997,32 @@ r535_gsp_rpc_get_gsp_static_info(struct nvkm_gsp *gsp)
        return 0;
 }
 
+static void
+nvkm_gsp_mem_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_mem *mem)
+{
+       if (mem->data) {
+               /*
+                * Poison the buffer to catch any unexpected access from
+                * GSP-RM if the buffer was prematurely freed.
+                */
+               memset(mem->data, 0xFF, mem->size);
+
+               dma_free_coherent(gsp->subdev.device->dev, mem->size, mem->data, mem->addr);
+               memset(mem, 0, sizeof(*mem));
+       }
+}
+
+static int
+nvkm_gsp_mem_ctor(struct nvkm_gsp *gsp, size_t size, struct nvkm_gsp_mem *mem)
+{
+       mem->size = size;
+       mem->data = dma_alloc_coherent(gsp->subdev.device->dev, size, &mem->addr, GFP_KERNEL);
+       if (WARN_ON(!mem->data))
+               return -ENOMEM;
+
+       return 0;
+}
+
 static int
 r535_gsp_postinit(struct nvkm_gsp *gsp)
 {
@@ -1024,6 +1050,13 @@ r535_gsp_postinit(struct nvkm_gsp *gsp)
 
        nvkm_inth_allow(&gsp->subdev.inth);
        nvkm_wr32(device, 0x110004, 0x00000040);
+
+       /* Release the DMA buffers that were needed only for boot and init */
+       nvkm_gsp_mem_dtor(gsp, &gsp->boot.fw);
+       nvkm_gsp_mem_dtor(gsp, &gsp->libos);
+       nvkm_gsp_mem_dtor(gsp, &gsp->rmargs);
+       nvkm_gsp_mem_dtor(gsp, &gsp->wpr_meta);
+
        return ret;
 }
 
@@ -1532,27 +1565,6 @@ r535_gsp_msg_run_cpu_sequencer(void *priv, u32 fn, void *repv, u32 repc)
        return 0;
 }
 
-static void
-nvkm_gsp_mem_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_mem *mem)
-{
-       if (mem->data) {
-               dma_free_coherent(gsp->subdev.device->dev, mem->size, mem->data, mem->addr);
-               mem->data = NULL;
-       }
-}
-
-static int
-nvkm_gsp_mem_ctor(struct nvkm_gsp *gsp, u32 size, struct nvkm_gsp_mem *mem)
-{
-       mem->size = size;
-       mem->data = dma_alloc_coherent(gsp->subdev.device->dev, size, &mem->addr, GFP_KERNEL);
-       if (WARN_ON(!mem->data))
-               return -ENOMEM;
-
-       return 0;
-}
-
-
 static int
 r535_gsp_booter_unload(struct nvkm_gsp *gsp, u32 mbox0, u32 mbox1)
 {
@@ -1938,20 +1950,20 @@ nvkm_gsp_radix3_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_radix3 *rx3)
  * See kgspCreateRadix3_IMPL
  */
 static int
-nvkm_gsp_radix3_sg(struct nvkm_device *device, struct sg_table *sgt, u64 size,
+nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size,
                   struct nvkm_gsp_radix3 *rx3)
 {
        u64 addr;
 
        for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) {
                u64 *ptes;
-               int idx;
+               size_t bufsize;
+               int ret, idx;
 
-               rx3->mem[i].size = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE);
-               rx3->mem[i].data = dma_alloc_coherent(device->dev, rx3->mem[i].size,
-                                                     &rx3->mem[i].addr, GFP_KERNEL);
-               if (WARN_ON(!rx3->mem[i].data))
-                       return -ENOMEM;
+               bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE);
+               ret = nvkm_gsp_mem_ctor(gsp, bufsize, &rx3->mem[i]);
+               if (ret)
+                       return ret;
 
                ptes = rx3->mem[i].data;
                if (i == 2) {
@@ -1991,7 +2003,7 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
                if (ret)
                        return ret;
 
-               ret = nvkm_gsp_radix3_sg(gsp->subdev.device, &gsp->sr.sgt, len, &gsp->sr.radix3);
+               ret = nvkm_gsp_radix3_sg(gsp, &gsp->sr.sgt, len, &gsp->sr.radix3);
                if (ret)
                        return ret;
 
@@ -2150,6 +2162,11 @@ r535_gsp_dtor(struct nvkm_gsp *gsp)
        mutex_destroy(&gsp->cmdq.mutex);
 
        r535_gsp_dtor_fws(gsp);
+
+       nvkm_gsp_mem_dtor(gsp, &gsp->shm.mem);
+       nvkm_gsp_mem_dtor(gsp, &gsp->loginit);
+       nvkm_gsp_mem_dtor(gsp, &gsp->logintr);
+       nvkm_gsp_mem_dtor(gsp, &gsp->logrm);
 }
 
 int
@@ -2194,7 +2211,7 @@ r535_gsp_oneinit(struct nvkm_gsp *gsp)
        memcpy(gsp->sig.data, data, size);
 
        /* Build radix3 page table for ELF image. */
-       ret = nvkm_gsp_radix3_sg(device, &gsp->fw.mem.sgt, gsp->fw.len, &gsp->radix3);
+       ret = nvkm_gsp_radix3_sg(gsp, &gsp->fw.mem.sgt, gsp->fw.len, &gsp->radix3);
        if (ret)
                return ret;
 
index 85b3b4871a1d63bf5a8cb2315a25dfd5ef2b8b70..fdd768bbd487c24b545da7aba2d0d45f63784293 100644 (file)
@@ -1985,8 +1985,10 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
                clock = vop2_set_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags);
        }
 
-       if (!clock)
+       if (!clock) {
+               vop2_unlock(vop2);
                return;
+       }
 
        if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
            !(vp_data->feature & VOP2_VP_FEATURE_OUTPUT_10BIT))
index 85f082396d42da982589fe69183c71743c69a89b..d442b893275b971a53adc42b3a06973eebd8bdbb 100644 (file)
@@ -1178,21 +1178,24 @@ static void drm_sched_run_job_work(struct work_struct *w)
        struct drm_sched_entity *entity;
        struct dma_fence *fence;
        struct drm_sched_fence *s_fence;
-       struct drm_sched_job *sched_job = NULL;
+       struct drm_sched_job *sched_job;
        int r;
 
        if (READ_ONCE(sched->pause_submit))
                return;
 
        /* Find entity with a ready job */
-       while (!sched_job && (entity = drm_sched_select_entity(sched))) {
-               sched_job = drm_sched_entity_pop_job(entity);
-               if (!sched_job)
-                       complete_all(&entity->entity_idle);
-       }
+       entity = drm_sched_select_entity(sched);
        if (!entity)
                return; /* No more work */
 
+       sched_job = drm_sched_entity_pop_job(entity);
+       if (!sched_job) {
+               complete_all(&entity->entity_idle);
+               drm_sched_run_job_queue(sched);
+               return;
+       }
+
        s_fence = sched_job->s_fence;
 
        atomic_add(sched_job->credits, &sched->credit_count);
index ea2af6bd9abebcf381cc6a1a245e8cc1f044a656..fee6bec757d1ac2e37918b5b16e97c4331cc0401 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/prime_numbers.h>
 #include <linux/sched/signal.h>
+#include <linux/sizes.h>
 
 #include <drm/drm_buddy.h>
 
@@ -18,6 +19,93 @@ static inline u64 get_size(int order, u64 chunk_size)
        return (1 << order) * chunk_size;
 }
 
+static void drm_test_buddy_alloc_contiguous(struct kunit *test)
+{
+       u64 mm_size, ps = SZ_4K, i, n_pages, total;
+       struct drm_buddy_block *block;
+       struct drm_buddy mm;
+       LIST_HEAD(left);
+       LIST_HEAD(middle);
+       LIST_HEAD(right);
+       LIST_HEAD(allocated);
+
+       mm_size = 16 * 3 * SZ_4K;
+
+       KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps));
+
+       /*
+        * Idea is to fragment the address space by alternating block
+        * allocations between three different lists; one for left, middle and
+        * right. We can then free a list to simulate fragmentation. In
+        * particular we want to exercise the DRM_BUDDY_CONTIGUOUS_ALLOCATION,
+        * including the try_harder path.
+        */
+
+       i = 0;
+       n_pages = mm_size / ps;
+       do {
+               struct list_head *list;
+               int slot = i % 3;
+
+               if (slot == 0)
+                       list = &left;
+               else if (slot == 1)
+                       list = &middle;
+               else
+                       list = &right;
+               KUNIT_ASSERT_FALSE_MSG(test,
+                                      drm_buddy_alloc_blocks(&mm, 0, mm_size,
+                                                             ps, ps, list, 0),
+                                      "buddy_alloc hit an error size=%d\n",
+                                      ps);
+       } while (++i < n_pages);
+
+       KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+                                                          3 * ps, ps, &allocated,
+                                                          DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+                              "buddy_alloc didn't error size=%d\n", 3 * ps);
+
+       drm_buddy_free_list(&mm, &middle);
+       KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+                                                          3 * ps, ps, &allocated,
+                                                          DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+                              "buddy_alloc didn't error size=%llu\n", 3 * ps);
+       KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+                                                          2 * ps, ps, &allocated,
+                                                          DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+                              "buddy_alloc didn't error size=%llu\n", 2 * ps);
+
+       drm_buddy_free_list(&mm, &right);
+       KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+                                                          3 * ps, ps, &allocated,
+                                                          DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+                              "buddy_alloc didn't error size=%llu\n", 3 * ps);
+       /*
+        * At this point we should have enough contiguous space for 2 blocks,
+        * however they are never buddies (since we freed middle and right) so
+        * will require the try_harder logic to find them.
+        */
+       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+                                                           2 * ps, ps, &allocated,
+                                                           DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+                              "buddy_alloc hit an error size=%d\n", 2 * ps);
+
+       drm_buddy_free_list(&mm, &left);
+       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+                                                           3 * ps, ps, &allocated,
+                                                           DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+                              "buddy_alloc hit an error size=%d\n", 3 * ps);
+
+       total = 0;
+       list_for_each_entry(block, &allocated, link)
+               total += drm_buddy_block_size(&mm, block);
+
+       KUNIT_ASSERT_EQ(test, total, ps * 2 + ps * 3);
+
+       drm_buddy_free_list(&mm, &allocated);
+       drm_buddy_fini(&mm);
+}
+
 static void drm_test_buddy_alloc_pathological(struct kunit *test)
 {
        u64 mm_size, size, start = 0;
@@ -280,6 +368,7 @@ static struct kunit_case drm_buddy_tests[] = {
        KUNIT_CASE(drm_test_buddy_alloc_optimistic),
        KUNIT_CASE(drm_test_buddy_alloc_pessimistic),
        KUNIT_CASE(drm_test_buddy_alloc_pathological),
+       KUNIT_CASE(drm_test_buddy_alloc_contiguous),
        {}
 };
 
index 68d9f6116bdfc3522ee5d6d94ef2bb763ec81090..777c20ceabab12f04f3f2062df3524ef1c2c0923 100644 (file)
@@ -10,7 +10,7 @@
 
 #include "xe_bo.h"
 
-#define i915_gem_object_is_shmem(obj) ((obj)->flags & XE_BO_CREATE_SYSTEM_BIT)
+#define i915_gem_object_is_shmem(obj) (0) /* We don't use shmem */
 
 static inline dma_addr_t i915_gem_object_get_dma_address(const struct xe_bo *bo, pgoff_t n)
 {
index 74391d9b11ae0e4cc77ecf9d0f5f47264e7adec6..e4db069f0db3f1fd27ed80eb84fc4544ea0831df 100644 (file)
@@ -134,8 +134,6 @@ static void xe_display_fini_nommio(struct drm_device *dev, void *dummy)
 
 int xe_display_init_nommio(struct xe_device *xe)
 {
-       int err;
-
        if (!xe->info.enable_display)
                return 0;
 
@@ -145,10 +143,6 @@ int xe_display_init_nommio(struct xe_device *xe)
        /* This must be called before any calls to HAS_PCH_* */
        intel_detect_pch(xe);
 
-       err = intel_power_domains_init(xe);
-       if (err)
-               return err;
-
        return drmm_add_action_or_reset(&xe->drm, xe_display_fini_nommio, xe);
 }
 
index bcfc4127c7c59f0fffc8e40df70a5b1c8222495f..254b1d3af4cb56888700f82b2a6b8fa3436e1a2a 100644 (file)
@@ -926,20 +926,24 @@ void xe_exec_queue_last_fence_put_unlocked(struct xe_exec_queue *q)
  * @q: The exec queue
  * @vm: The VM the engine does a bind or exec for
  *
- * Get last fence, does not take a ref
+ * Get last fence, takes a ref
  *
  * Returns: last fence if not signaled, dma fence stub if signaled
  */
 struct dma_fence *xe_exec_queue_last_fence_get(struct xe_exec_queue *q,
                                               struct xe_vm *vm)
 {
+       struct dma_fence *fence;
+
        xe_exec_queue_last_fence_lockdep_assert(q, vm);
 
        if (q->last_fence &&
            test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &q->last_fence->flags))
                xe_exec_queue_last_fence_put(q, vm);
 
-       return q->last_fence ? q->last_fence : dma_fence_get_stub();
+       fence = q->last_fence ? q->last_fence : dma_fence_get_stub();
+       dma_fence_get(fence);
+       return fence;
 }
 
 /**
index 3af2adec129561850bfb378c04ca2d7caacdf325..35474ddbaf97ecc974a6b55643e578dbcfe135f9 100644 (file)
@@ -437,7 +437,10 @@ static int all_fw_domain_init(struct xe_gt *gt)
                 * USM has its only SA pool to non-block behind user operations
                 */
                if (gt_to_xe(gt)->info.has_usm) {
-                       gt->usm.bb_pool = xe_sa_bo_manager_init(gt_to_tile(gt), SZ_1M, 16);
+                       struct xe_device *xe = gt_to_xe(gt);
+
+                       gt->usm.bb_pool = xe_sa_bo_manager_init(gt_to_tile(gt),
+                                                               IS_DGFX(xe) ? SZ_1M : SZ_512K, 16);
                        if (IS_ERR(gt->usm.bb_pool)) {
                                err = PTR_ERR(gt->usm.bb_pool);
                                goto err_force_wake;
index 9c2fe1697d6eef002e9b85ccd89a18648e654fee..73f08f1924df2ea8d4aaabb87eceaa13eff81d78 100644 (file)
@@ -335,7 +335,7 @@ int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len)
                return -EPROTO;
 
        asid = FIELD_GET(PFD_ASID, msg[1]);
-       pf_queue = &gt->usm.pf_queue[asid % NUM_PF_QUEUE];
+       pf_queue = gt->usm.pf_queue + (asid % NUM_PF_QUEUE);
 
        spin_lock_irqsave(&pf_queue->lock, flags);
        full = pf_queue_full(pf_queue);
index 5c6c5462425217c9301560a626d67ec7386bd418..70480c30560215ff7fece9a824fd01c92008562d 100644 (file)
@@ -170,11 +170,6 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m,
        if (!IS_DGFX(xe)) {
                /* Write out batch too */
                m->batch_base_ofs = NUM_PT_SLOTS * XE_PAGE_SIZE;
-               if (xe->info.has_usm) {
-                       batch = tile->primary_gt->usm.bb_pool->bo;
-                       m->usm_batch_base_ofs = m->batch_base_ofs;
-               }
-
                for (i = 0; i < batch->size;
                     i += vm->flags & XE_VM_FLAG_64K ? XE_64K_PAGE_SIZE :
                     XE_PAGE_SIZE) {
@@ -185,6 +180,24 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m,
                                  entry);
                        level++;
                }
+               if (xe->info.has_usm) {
+                       xe_tile_assert(tile, batch->size == SZ_1M);
+
+                       batch = tile->primary_gt->usm.bb_pool->bo;
+                       m->usm_batch_base_ofs = m->batch_base_ofs + SZ_1M;
+                       xe_tile_assert(tile, batch->size == SZ_512K);
+
+                       for (i = 0; i < batch->size;
+                            i += vm->flags & XE_VM_FLAG_64K ? XE_64K_PAGE_SIZE :
+                            XE_PAGE_SIZE) {
+                               entry = vm->pt_ops->pte_encode_bo(batch, i,
+                                                                 pat_index, 0);
+
+                               xe_map_wr(xe, &bo->vmap, map_ofs + level * 8, u64,
+                                         entry);
+                               level++;
+                       }
+               }
        } else {
                u64 batch_addr = xe_bo_addr(batch, 0, XE_PAGE_SIZE);
 
@@ -1204,8 +1217,11 @@ static bool no_in_syncs(struct xe_vm *vm, struct xe_exec_queue *q,
        }
        if (q) {
                fence = xe_exec_queue_last_fence_get(q, vm);
-               if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+               if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+                       dma_fence_put(fence);
                        return false;
+               }
+               dma_fence_put(fence);
        }
 
        return true;
index e45b37c3f0c262744f960d769eeed29a07ef14e7..ac19bfa3f798c08e48511af0f18e093f29f88eab 100644 (file)
@@ -20,8 +20,8 @@
 
 struct xe_pt_dir {
        struct xe_pt pt;
-       /** @dir: Directory structure for the xe_pt_walk functionality */
-       struct xe_ptw_dir dir;
+       /** @children: Array of page-table child nodes */
+       struct xe_ptw *children[XE_PDES];
 };
 
 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM)
@@ -44,7 +44,7 @@ static struct xe_pt_dir *as_xe_pt_dir(struct xe_pt *pt)
 
 static struct xe_pt *xe_pt_entry(struct xe_pt_dir *pt_dir, unsigned int index)
 {
-       return container_of(pt_dir->dir.entries[index], struct xe_pt, base);
+       return container_of(pt_dir->children[index], struct xe_pt, base);
 }
 
 static u64 __xe_pt_empty_pte(struct xe_tile *tile, struct xe_vm *vm,
@@ -65,6 +65,14 @@ static u64 __xe_pt_empty_pte(struct xe_tile *tile, struct xe_vm *vm,
                XE_PTE_NULL;
 }
 
+static void xe_pt_free(struct xe_pt *pt)
+{
+       if (pt->level)
+               kfree(as_xe_pt_dir(pt));
+       else
+               kfree(pt);
+}
+
 /**
  * xe_pt_create() - Create a page-table.
  * @vm: The vm to create for.
@@ -85,15 +93,19 @@ struct xe_pt *xe_pt_create(struct xe_vm *vm, struct xe_tile *tile,
 {
        struct xe_pt *pt;
        struct xe_bo *bo;
-       size_t size;
        int err;
 
-       size = !level ?  sizeof(struct xe_pt) : sizeof(struct xe_pt_dir) +
-               XE_PDES * sizeof(struct xe_ptw *);
-       pt = kzalloc(size, GFP_KERNEL);
+       if (level) {
+               struct xe_pt_dir *dir = kzalloc(sizeof(*dir), GFP_KERNEL);
+
+               pt = (dir) ? &dir->pt : NULL;
+       } else {
+               pt = kzalloc(sizeof(*pt), GFP_KERNEL);
+       }
        if (!pt)
                return ERR_PTR(-ENOMEM);
 
+       pt->level = level;
        bo = xe_bo_create_pin_map(vm->xe, tile, vm, SZ_4K,
                                  ttm_bo_type_kernel,
                                  XE_BO_CREATE_VRAM_IF_DGFX(tile) |
@@ -106,8 +118,7 @@ struct xe_pt *xe_pt_create(struct xe_vm *vm, struct xe_tile *tile,
                goto err_kfree;
        }
        pt->bo = bo;
-       pt->level = level;
-       pt->base.dir = level ? &as_xe_pt_dir(pt)->dir : NULL;
+       pt->base.children = level ? as_xe_pt_dir(pt)->children : NULL;
 
        if (vm->xef)
                xe_drm_client_add_bo(vm->xef->client, pt->bo);
@@ -116,7 +127,7 @@ struct xe_pt *xe_pt_create(struct xe_vm *vm, struct xe_tile *tile,
        return pt;
 
 err_kfree:
-       kfree(pt);
+       xe_pt_free(pt);
        return ERR_PTR(err);
 }
 
@@ -193,7 +204,7 @@ void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred)
                                              deferred);
                }
        }
-       kfree(pt);
+       xe_pt_free(pt);
 }
 
 /**
@@ -358,7 +369,7 @@ xe_pt_insert_entry(struct xe_pt_stage_bind_walk *xe_walk, struct xe_pt *parent,
                struct iosys_map *map = &parent->bo->vmap;
 
                if (unlikely(xe_child))
-                       parent->base.dir->entries[offset] = &xe_child->base;
+                       parent->base.children[offset] = &xe_child->base;
 
                xe_pt_write(xe_walk->vm->xe, map, offset, pte);
                parent->num_live++;
@@ -853,7 +864,7 @@ static void xe_pt_commit_bind(struct xe_vma *vma,
                                xe_pt_destroy(xe_pt_entry(pt_dir, j_),
                                              xe_vma_vm(vma)->flags, deferred);
 
-                       pt_dir->dir.entries[j_] = &newpte->base;
+                       pt_dir->children[j_] = &newpte->base;
                }
                kfree(entries[i].pt_entries);
        }
@@ -1507,7 +1518,7 @@ xe_pt_commit_unbind(struct xe_vma *vma,
                                        xe_pt_destroy(xe_pt_entry(pt_dir, i),
                                                      xe_vma_vm(vma)->flags, deferred);
 
-                               pt_dir->dir.entries[i] = NULL;
+                               pt_dir->children[i] = NULL;
                        }
                }
        }
index 8f6c8d063f39f0293a6c4d966c009dfc24ca9045..b8b3d2aea4923d0ac087f6a2c972652aba8efc6f 100644 (file)
@@ -74,7 +74,7 @@ int xe_pt_walk_range(struct xe_ptw *parent, unsigned int level,
                     u64 addr, u64 end, struct xe_pt_walk *walk)
 {
        pgoff_t offset = xe_pt_offset(addr, level, walk);
-       struct xe_ptw **entries = parent->dir ? parent->dir->entries : NULL;
+       struct xe_ptw **entries = parent->children ? parent->children : NULL;
        const struct xe_pt_walk_ops *ops = walk->ops;
        enum page_walk_action action;
        struct xe_ptw *child;
index ec3d1e9efa6d514ae21bb4b4a1b35a0bc2baf59c..5ecc4d2f0f6536b7ec79033f80f556ce1f00edc5 100644 (file)
@@ -8,28 +8,15 @@
 #include <linux/pagewalk.h>
 #include <linux/types.h>
 
-struct xe_ptw_dir;
-
 /**
  * struct xe_ptw - base class for driver pagetable subclassing.
- * @dir: Pointer to an array of children if any.
+ * @children: Pointer to an array of children if any.
  *
  * Drivers could subclass this, and if it's a page-directory, typically
- * embed the xe_ptw_dir::entries array in the same allocation.
+ * embed an array of xe_ptw pointers.
  */
 struct xe_ptw {
-       struct xe_ptw_dir *dir;
-};
-
-/**
- * struct xe_ptw_dir - page directory structure
- * @entries: Array holding page directory children.
- *
- * It is the responsibility of the user to ensure @entries is
- * correctly sized.
- */
-struct xe_ptw_dir {
-       struct xe_ptw *entries[0];
+       struct xe_ptw **children;
 };
 
 /**
index d35d9ec58e86f95c8244fc02e6a9709b63ccf93a..372378e89e989239833879e23d2e62a2fd573b54 100644 (file)
@@ -151,6 +151,11 @@ xe_range_fence_tree_next(struct xe_range_fence *rfence, u64 start, u64 last)
        return xe_range_fence_tree_iter_next(rfence, start, last);
 }
 
+static void xe_range_fence_free(struct xe_range_fence *rfence)
+{
+       kfree(rfence);
+}
+
 const struct xe_range_fence_ops xe_range_fence_kfree_ops = {
-       .free = (void (*)(struct xe_range_fence *rfence)) kfree,
+       .free = xe_range_fence_free,
 };
index 01106a1156ad82ab30378b29abf3f18d55b64fe3..4e2ccad0e52fabaf43ea26ddc1dd86f2294662a1 100644 (file)
@@ -274,7 +274,6 @@ int xe_sched_job_last_fence_add_dep(struct xe_sched_job *job, struct xe_vm *vm)
        struct dma_fence *fence;
 
        fence = xe_exec_queue_last_fence_get(job->q, vm);
-       dma_fence_get(fence);
 
        return drm_sched_job_add_dependency(&job->drm, fence);
 }
index e4c220cf9115e9d52fc7b1e9440e0e44ba247c46..aab92bee1d7cf2ff52ec07befe0dcc220325a649 100644 (file)
@@ -307,7 +307,6 @@ xe_sync_in_fence_get(struct xe_sync_entry *sync, int num_sync,
        /* Easy case... */
        if (!num_in_fence) {
                fence = xe_exec_queue_last_fence_get(q, vm);
-               dma_fence_get(fence);
                return fence;
        }
 
@@ -322,7 +321,6 @@ xe_sync_in_fence_get(struct xe_sync_entry *sync, int num_sync,
                }
        }
        fences[current_fence++] = xe_exec_queue_last_fence_get(q, vm);
-       dma_fence_get(fences[current_fence - 1]);
        cf = dma_fence_array_create(num_in_fence, fences,
                                    vm->composite_fence_ctx,
                                    vm->composite_fence_seqno++,
index 30db264d34a32315c6fc725c16dc24f6936da8e8..7b00faa672879c3b568c3ee3f3d9c20c54f527c9 100644 (file)
@@ -37,8 +37,6 @@
 #include "generated/xe_wa_oob.h"
 #include "xe_wa.h"
 
-#define TEST_VM_ASYNC_OPS_ERROR
-
 static struct drm_gem_object *xe_vm_obj(struct xe_vm *vm)
 {
        return vm->gpuvm.r_obj;
@@ -114,11 +112,8 @@ retry:
                                          num_pages - pinned,
                                          read_only ? 0 : FOLL_WRITE,
                                          &pages[pinned]);
-               if (ret < 0) {
-                       if (in_kthread)
-                               ret = 0;
+               if (ret < 0)
                        break;
-               }
 
                pinned += ret;
                ret = 0;
@@ -1000,9 +995,16 @@ int xe_vm_prepare_vma(struct drm_exec *exec, struct xe_vma *vma,
        int err;
 
        XE_WARN_ON(!vm);
-       err = drm_exec_prepare_obj(exec, xe_vm_obj(vm), num_shared);
-       if (!err && bo && !bo->vm)
-               err = drm_exec_prepare_obj(exec, &bo->ttm.base, num_shared);
+       if (num_shared)
+               err = drm_exec_prepare_obj(exec, xe_vm_obj(vm), num_shared);
+       else
+               err = drm_exec_lock_obj(exec, xe_vm_obj(vm));
+       if (!err && bo && !bo->vm) {
+               if (num_shared)
+                       err = drm_exec_prepare_obj(exec, &bo->ttm.base, num_shared);
+               else
+                       err = drm_exec_lock_obj(exec, &bo->ttm.base);
+       }
 
        return err;
 }
@@ -1984,6 +1986,7 @@ static int xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
                                        xe_exec_queue_last_fence_get(wait_exec_queue, vm);
 
                                xe_sync_entry_signal(&syncs[i], NULL, fence);
+                               dma_fence_put(fence);
                        }
                }
 
@@ -2064,7 +2067,6 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo,
        struct drm_gem_object *obj = bo ? &bo->ttm.base : NULL;
        struct drm_gpuva_ops *ops;
        struct drm_gpuva_op *__op;
-       struct xe_vma_op *op;
        struct drm_gpuvm_bo *vm_bo;
        int err;
 
@@ -2111,15 +2113,6 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo,
        if (IS_ERR(ops))
                return ops;
 
-#ifdef TEST_VM_ASYNC_OPS_ERROR
-       if (operation & FORCE_ASYNC_OP_ERROR) {
-               op = list_first_entry_or_null(&ops->list, struct xe_vma_op,
-                                             base.entry);
-               if (op)
-                       op->inject_error = true;
-       }
-#endif
-
        drm_gpuva_for_each_op(__op, ops) {
                struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
 
@@ -2199,8 +2192,10 @@ static u64 xe_vma_max_pte_size(struct xe_vma *vma)
                return SZ_1G;
        else if (vma->gpuva.flags & XE_VMA_PTE_2M)
                return SZ_2M;
+       else if (vma->gpuva.flags & XE_VMA_PTE_4K)
+               return SZ_4K;
 
-       return SZ_4K;
+       return SZ_1G;   /* Uninitialized, used max size */
 }
 
 static u64 xe_vma_set_pte_size(struct xe_vma *vma, u64 size)
@@ -2530,13 +2525,25 @@ retry_userptr:
        }
        drm_exec_fini(&exec);
 
-       if (err == -EAGAIN && xe_vma_is_userptr(vma)) {
+       if (err == -EAGAIN) {
                lockdep_assert_held_write(&vm->lock);
-               err = xe_vma_userptr_pin_pages(to_userptr_vma(vma));
-               if (!err)
-                       goto retry_userptr;
 
-               trace_xe_vma_fail(vma);
+               if (op->base.op == DRM_GPUVA_OP_REMAP) {
+                       if (!op->remap.unmap_done)
+                               vma = gpuva_to_vma(op->base.remap.unmap->va);
+                       else if (op->remap.prev)
+                               vma = op->remap.prev;
+                       else
+                               vma = op->remap.next;
+               }
+
+               if (xe_vma_is_userptr(vma)) {
+                       err = xe_vma_userptr_pin_pages(to_userptr_vma(vma));
+                       if (!err)
+                               goto retry_userptr;
+
+                       trace_xe_vma_fail(vma);
+               }
        }
 
        return err;
@@ -2548,13 +2555,6 @@ static int xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op)
 
        lockdep_assert_held_write(&vm->lock);
 
-#ifdef TEST_VM_ASYNC_OPS_ERROR
-       if (op->inject_error) {
-               op->inject_error = false;
-               return -ENOMEM;
-       }
-#endif
-
        switch (op->base.op) {
        case DRM_GPUVA_OP_MAP:
                ret = __xe_vma_op_execute(vm, op->map.vma, op);
@@ -2669,7 +2669,7 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm *vm,
 {
        int i;
 
-       for (i = num_ops_list - 1; i; ++i) {
+       for (i = num_ops_list - 1; i >= 0; --i) {
                struct drm_gpuva_ops *__ops = ops[i];
                struct drm_gpuva_op *__op;
 
@@ -2714,16 +2714,9 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
        return 0;
 }
 
-#ifdef TEST_VM_ASYNC_OPS_ERROR
-#define SUPPORTED_FLAGS        \
-       (FORCE_ASYNC_OP_ERROR | DRM_XE_VM_BIND_FLAG_READONLY | \
-        DRM_XE_VM_BIND_FLAG_IMMEDIATE | DRM_XE_VM_BIND_FLAG_NULL | 0xffff)
-#else
 #define SUPPORTED_FLAGS        \
        (DRM_XE_VM_BIND_FLAG_READONLY | \
-        DRM_XE_VM_BIND_FLAG_IMMEDIATE | DRM_XE_VM_BIND_FLAG_NULL | \
-        0xffff)
-#endif
+        DRM_XE_VM_BIND_FLAG_IMMEDIATE | DRM_XE_VM_BIND_FLAG_NULL)
 #define XE_64K_PAGE_MASK 0xffffull
 #define ALL_DRM_XE_SYNCS_FLAGS (DRM_XE_SYNCS_FLAG_WAIT_FOR_OP)
 
index 1fec66ae2eb2dd0309590ec7b84ad34cfa6a1b25..5ac9c5bebabc3cf3ecf528f51f8aa92cebc410ef 100644 (file)
@@ -21,9 +21,6 @@ struct xe_bo;
 struct xe_sync_entry;
 struct xe_vm;
 
-#define TEST_VM_ASYNC_OPS_ERROR
-#define FORCE_ASYNC_OP_ERROR   BIT(31)
-
 #define XE_VMA_READ_ONLY       DRM_GPUVA_USERBITS
 #define XE_VMA_DESTROYED       (DRM_GPUVA_USERBITS << 1)
 #define XE_VMA_ATOMIC_PTE_BIT  (DRM_GPUVA_USERBITS << 2)
@@ -360,11 +357,6 @@ struct xe_vma_op {
        /** @flags: operation flags */
        enum xe_vma_op_flags flags;
 
-#ifdef TEST_VM_ASYNC_OPS_ERROR
-       /** @inject_error: inject error to test async op error handling */
-       bool inject_error;
-#endif
-
        union {
                /** @map: VMA map operation specific data */
                struct xe_vma_op_map map;
index 6ef0c88e3e60a6910eb60f052107dafac9f01d1c..d2f3f234f29dea35b2bfb37ef693ba9d6a9b8bf6 100644 (file)
@@ -203,6 +203,8 @@ struct hidpp_device {
        struct hidpp_scroll_counter vertical_wheel_counter;
 
        u8 wireless_feature_index;
+
+       bool connected_once;
 };
 
 /* HID++ 1.0 error codes */
@@ -988,8 +990,13 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp)
        hidpp->protocol_minor = response.rap.params[1];
 
 print_version:
-       hid_info(hidpp->hid_dev, "HID++ %u.%u device connected.\n",
-                hidpp->protocol_major, hidpp->protocol_minor);
+       if (!hidpp->connected_once) {
+               hid_info(hidpp->hid_dev, "HID++ %u.%u device connected.\n",
+                        hidpp->protocol_major, hidpp->protocol_minor);
+               hidpp->connected_once = true;
+       } else
+               hid_dbg(hidpp->hid_dev, "HID++ %u.%u device connected.\n",
+                        hidpp->protocol_major, hidpp->protocol_minor);
        return 0;
 }
 
@@ -4184,7 +4191,7 @@ static void hidpp_connect_event(struct work_struct *work)
        /* Get device version to check if it is connected */
        ret = hidpp_root_get_protocol_version(hidpp);
        if (ret) {
-               hid_info(hidpp->hid_dev, "Disconnected\n");
+               hid_dbg(hidpp->hid_dev, "Disconnected\n");
                if (hidpp->battery.ps) {
                        hidpp->battery.online = false;
                        hidpp->battery.status = POWER_SUPPLY_STATUS_UNKNOWN;
index fd5b0637dad683e7b20c929974c958e79936880c..3e91e4d6ba6fa335c7f5988638791d3df8d1773a 100644 (file)
@@ -2151,6 +2151,10 @@ static const struct hid_device_id mt_devices[] = {
                HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
                        USB_VENDOR_ID_SYNAPTICS, 0xcd7e) },
 
+       { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+               HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+                       USB_VENDOR_ID_SYNAPTICS, 0xcddc) },
+
        { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
                HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
                        USB_VENDOR_ID_SYNAPTICS, 0xce08) },
index aa6cb033bb06b77f182e6df441a04e1b016aaef5..03d5601ce807b3b1d49ed88bc923774d71ace572 100644 (file)
@@ -722,6 +722,8 @@ void ishtp_bus_remove_all_clients(struct ishtp_device *ishtp_dev,
        spin_lock_irqsave(&ishtp_dev->cl_list_lock, flags);
        list_for_each_entry(cl, &ishtp_dev->cl_list, link) {
                cl->state = ISHTP_CL_DISCONNECTED;
+               if (warm_reset && cl->device->reference_count)
+                       continue;
 
                /*
                 * Wake any pending process. The waiter would check dev->state
index 82c907f01bd3b66af02efa1d313f3bb2f7cb7209..8a7f2f6a4f86864cd5783ed51852f56cef614d5f 100644 (file)
@@ -49,7 +49,9 @@ static void ishtp_read_list_flush(struct ishtp_cl *cl)
        list_for_each_entry_safe(rb, next, &cl->dev->read_list.list, list)
                if (rb->cl && ishtp_cl_cmp_id(cl, rb->cl)) {
                        list_del(&rb->list);
-                       ishtp_io_rb_free(rb);
+                       spin_lock(&cl->free_list_spinlock);
+                       list_add_tail(&rb->list, &cl->free_rb_list.list);
+                       spin_unlock(&cl->free_list_spinlock);
                }
        spin_unlock_irqrestore(&cl->dev->read_list_spinlock, flags);
 }
index b613f11ed9498d7045f8649496049dc1b0b91839..2bc45b24075c3fe4b70ef222bbd21a4ee11eeb21 100644 (file)
@@ -2087,7 +2087,7 @@ static int wacom_allocate_inputs(struct wacom *wacom)
        return 0;
 }
 
-static int wacom_register_inputs(struct wacom *wacom)
+static int wacom_setup_inputs(struct wacom *wacom)
 {
        struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
        struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
@@ -2106,10 +2106,6 @@ static int wacom_register_inputs(struct wacom *wacom)
                input_free_device(pen_input_dev);
                wacom_wac->pen_input = NULL;
                pen_input_dev = NULL;
-       } else {
-               error = input_register_device(pen_input_dev);
-               if (error)
-                       goto fail;
        }
 
        error = wacom_setup_touch_input_capabilities(touch_input_dev, wacom_wac);
@@ -2118,10 +2114,6 @@ static int wacom_register_inputs(struct wacom *wacom)
                input_free_device(touch_input_dev);
                wacom_wac->touch_input = NULL;
                touch_input_dev = NULL;
-       } else {
-               error = input_register_device(touch_input_dev);
-               if (error)
-                       goto fail;
        }
 
        error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
@@ -2130,7 +2122,34 @@ static int wacom_register_inputs(struct wacom *wacom)
                input_free_device(pad_input_dev);
                wacom_wac->pad_input = NULL;
                pad_input_dev = NULL;
-       } else {
+       }
+
+       return 0;
+}
+
+static int wacom_register_inputs(struct wacom *wacom)
+{
+       struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
+       struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+       int error = 0;
+
+       pen_input_dev = wacom_wac->pen_input;
+       touch_input_dev = wacom_wac->touch_input;
+       pad_input_dev = wacom_wac->pad_input;
+
+       if (pen_input_dev) {
+               error = input_register_device(pen_input_dev);
+               if (error)
+                       goto fail;
+       }
+
+       if (touch_input_dev) {
+               error = input_register_device(touch_input_dev);
+               if (error)
+                       goto fail;
+       }
+
+       if (pad_input_dev) {
                error = input_register_device(pad_input_dev);
                if (error)
                        goto fail;
@@ -2383,6 +2402,20 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
        if (error)
                goto fail;
 
+       error = wacom_setup_inputs(wacom);
+       if (error)
+               goto fail;
+
+       if (features->type == HID_GENERIC)
+               connect_mask |= HID_CONNECT_DRIVER;
+
+       /* Regular HID work starts now */
+       error = hid_hw_start(hdev, connect_mask);
+       if (error) {
+               hid_err(hdev, "hw start failed\n");
+               goto fail;
+       }
+
        error = wacom_register_inputs(wacom);
        if (error)
                goto fail;
@@ -2397,16 +2430,6 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
                        goto fail;
        }
 
-       if (features->type == HID_GENERIC)
-               connect_mask |= HID_CONNECT_DRIVER;
-
-       /* Regular HID work starts now */
-       error = hid_hw_start(hdev, connect_mask);
-       if (error) {
-               hid_err(hdev, "hw start failed\n");
-               goto fail;
-       }
-
        if (!wireless) {
                /* Note that if query fails it is not a hard failure */
                wacom_query_tablet_data(wacom);
index da8a01fedd3944a7588aad5e2a523b44b2b2797c..fbe10fbc5769e53affe44a0826a55853b306c0ee 100644 (file)
@@ -2575,7 +2575,14 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
                                wacom_wac->hid_data.tipswitch);
                input_report_key(input, wacom_wac->tool[0], sense);
                if (wacom_wac->serial[0]) {
-                       input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
+                       /*
+                        * xf86-input-wacom does not accept a serial number
+                        * of '0'. Report the low 32 bits if possible, but
+                        * if they are zero, report the upper ones instead.
+                        */
+                       __u32 serial_lo = wacom_wac->serial[0] & 0xFFFFFFFFu;
+                       __u32 serial_hi = wacom_wac->serial[0] >> 32;
+                       input_event(input, EV_MSC, MSC_SERIAL, (int)(serial_lo ? serial_lo : serial_hi));
                        input_report_abs(input, ABS_MISC, sense ? id : 0);
                }
 
index f6e1e55e82922be6f67a98046b4f74c3159625d9..4acc1858d8acf799c20e5c2061431d35adc8db10 100644 (file)
@@ -195,6 +195,8 @@ struct aspeed_pwm_tacho_data {
        u8 fan_tach_ch_source[MAX_ASPEED_FAN_TACH_CHANNELS];
        struct aspeed_cooling_device *cdev[8];
        const struct attribute_group *groups[3];
+       /* protects access to shared ASPEED_PTCR_RESULT */
+       struct mutex tach_lock;
 };
 
 enum type { TYPEM, TYPEN, TYPEO };
@@ -529,6 +531,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
        u8 fan_tach_ch_source, type, mode, both;
        int ret;
 
+       mutex_lock(&priv->tach_lock);
+
        regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
        regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);
 
@@ -546,6 +550,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
                ASPEED_RPM_STATUS_SLEEP_USEC,
                usec);
 
+       mutex_unlock(&priv->tach_lock);
+
        /* return -ETIMEDOUT if we didn't get an answer. */
        if (ret)
                return ret;
@@ -915,6 +921,7 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
+       mutex_init(&priv->tach_lock);
        priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
                        &aspeed_pwm_tacho_regmap_config);
        if (IS_ERR(priv->regmap))
index ba82d1e79c131678c0c673bd5c0d9d77b09fdf1a..b8fc8d1ef20dfcb6132a168425df2d7e2653afa4 100644 (file)
@@ -41,7 +41,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
 
 #define PKG_SYSFS_ATTR_NO      1       /* Sysfs attribute for package temp */
 #define BASE_SYSFS_ATTR_NO     2       /* Sysfs Base attr no for coretemp */
-#define NUM_REAL_CORES         128     /* Number of Real cores per cpu */
+#define NUM_REAL_CORES         512     /* Number of Real cores per cpu */
 #define CORETEMP_NAME_LENGTH   28      /* String Length of attrs */
 #define MAX_CORE_ATTRS         4       /* Maximum no of basic attrs */
 #define TOTAL_ATTRS            (MAX_CORE_ATTRS + 1)
@@ -419,7 +419,7 @@ static ssize_t show_temp(struct device *dev,
 }
 
 static int create_core_attrs(struct temp_data *tdata, struct device *dev,
-                            int attr_no)
+                            int index)
 {
        int i;
        static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
@@ -431,13 +431,20 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
        };
 
        for (i = 0; i < tdata->attr_size; i++) {
+               /*
+                * We map the attr number to core id of the CPU
+                * The attr number is always core id + 2
+                * The Pkgtemp will always show up as temp1_*, if available
+                */
+               int attr_no = tdata->is_pkg_data ? 1 : tdata->cpu_core_id + 2;
+
                snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH,
                         "temp%d_%s", attr_no, suffixes[i]);
                sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
                tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
                tdata->sd_attrs[i].dev_attr.attr.mode = 0444;
                tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
-               tdata->sd_attrs[i].index = attr_no;
+               tdata->sd_attrs[i].index = index;
                tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr;
        }
        tdata->attr_group.attrs = tdata->attrs;
@@ -495,30 +502,25 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
        struct platform_data *pdata = platform_get_drvdata(pdev);
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        u32 eax, edx;
-       int err, index, attr_no;
+       int err, index;
 
        if (!housekeeping_cpu(cpu, HK_TYPE_MISC))
                return 0;
 
        /*
-        * Find attr number for sysfs:
-        * We map the attr number to core id of the CPU
-        * The attr number is always core id + 2
-        * The Pkgtemp will always show up as temp1_*, if available
+        * Get the index of tdata in pdata->core_data[]
+        * tdata for package: pdata->core_data[1]
+        * tdata for core: pdata->core_data[2] .. pdata->core_data[NUM_REAL_CORES + 1]
         */
        if (pkg_flag) {
-               attr_no = PKG_SYSFS_ATTR_NO;
+               index = PKG_SYSFS_ATTR_NO;
        } else {
-               index = ida_alloc(&pdata->ida, GFP_KERNEL);
+               index = ida_alloc_max(&pdata->ida, NUM_REAL_CORES - 1, GFP_KERNEL);
                if (index < 0)
                        return index;
-               pdata->cpu_map[index] = topology_core_id(cpu);
-               attr_no = index + BASE_SYSFS_ATTR_NO;
-       }
 
-       if (attr_no > MAX_CORE_DATA - 1) {
-               err = -ERANGE;
-               goto ida_free;
+               pdata->cpu_map[index] = topology_core_id(cpu);
+               index += BASE_SYSFS_ATTR_NO;
        }
 
        tdata = init_temp_data(cpu, pkg_flag);
@@ -544,20 +546,20 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
                if (get_ttarget(tdata, &pdev->dev) >= 0)
                        tdata->attr_size++;
 
-       pdata->core_data[attr_no] = tdata;
+       pdata->core_data[index] = tdata;
 
        /* Create sysfs interfaces */
-       err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no);
+       err = create_core_attrs(tdata, pdata->hwmon_dev, index);
        if (err)
                goto exit_free;
 
        return 0;
 exit_free:
-       pdata->core_data[attr_no] = NULL;
+       pdata->core_data[index] = NULL;
        kfree(tdata);
 ida_free:
        if (!pkg_flag)
-               ida_free(&pdata->ida, index);
+               ida_free(&pdata->ida, index - BASE_SYSFS_ATTR_NO);
        return err;
 }
 
index aebd3c12020bfd5d104c089354da0557de93547d..c381c22135a217b71e82f8282699cfbe14749ded 100644 (file)
@@ -725,6 +725,9 @@ irqreturn_t rkisp1_capture_isr(int irq, void *ctx)
        unsigned int i;
        u32 status;
 
+       if (!rkisp1->irqs_enabled)
+               return IRQ_NONE;
+
        status = rkisp1_read(rkisp1, RKISP1_CIF_MI_MIS);
        if (!status)
                return IRQ_NONE;
index 4b6b28c05b8916b7e5e079b6d2791009907c22db..b757f75edecf75256525e378151fe217c88ef2c4 100644 (file)
@@ -450,6 +450,7 @@ struct rkisp1_debug {
  * @debug:        debug params to be exposed on debugfs
  * @info:         version-specific ISP information
  * @irqs:          IRQ line numbers
+ * @irqs_enabled:  the hardware is enabled and can cause interrupts
  */
 struct rkisp1_device {
        void __iomem *base_addr;
@@ -471,6 +472,7 @@ struct rkisp1_device {
        struct rkisp1_debug debug;
        const struct rkisp1_info *info;
        int irqs[RKISP1_NUM_IRQS];
+       bool irqs_enabled;
 };
 
 /*
index b6e47e2f1b94916e51ec86b38d12b37ae186609d..4202642e052392a946761ecb76d3cfa771956e07 100644 (file)
@@ -196,6 +196,9 @@ irqreturn_t rkisp1_csi_isr(int irq, void *ctx)
        struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
        u32 val, status;
 
+       if (!rkisp1->irqs_enabled)
+               return IRQ_NONE;
+
        status = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_MIS);
        if (!status)
                return IRQ_NONE;
index f96f821a7b50d0f10db51932d2b82986dcb16957..73cf08a740118c05328fdd3f1a9d52a6e935c4e0 100644 (file)
@@ -305,6 +305,24 @@ static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
 {
        struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
 
+       rkisp1->irqs_enabled = false;
+       /* Make sure the IRQ handler will see the above */
+       mb();
+
+       /*
+        * Wait until any running IRQ handler has returned. The IRQ handler
+        * may get called even after this (as it's a shared interrupt line)
+        * but the 'irqs_enabled' flag will make the handler return immediately.
+        */
+       for (unsigned int il = 0; il < ARRAY_SIZE(rkisp1->irqs); ++il) {
+               if (rkisp1->irqs[il] == -1)
+                       continue;
+
+               /* Skip if the irq line is the same as previous */
+               if (il == 0 || rkisp1->irqs[il - 1] != rkisp1->irqs[il])
+                       synchronize_irq(rkisp1->irqs[il]);
+       }
+
        clk_bulk_disable_unprepare(rkisp1->clk_size, rkisp1->clks);
        return pinctrl_pm_select_sleep_state(dev);
 }
@@ -321,6 +339,10 @@ static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
        if (ret)
                return ret;
 
+       rkisp1->irqs_enabled = true;
+       /* Make sure the IRQ handler will see the above */
+       mb();
+
        return 0;
 }
 
@@ -559,7 +581,7 @@ static int rkisp1_probe(struct platform_device *pdev)
                                rkisp1->irqs[il] = irq;
                }
 
-               ret = devm_request_irq(dev, irq, info->isrs[i].isr, 0,
+               ret = devm_request_irq(dev, irq, info->isrs[i].isr, IRQF_SHARED,
                                       dev_driver_string(dev), dev);
                if (ret) {
                        dev_err(dev, "request irq failed: %d\n", ret);
index f00873d31c42b702d239e9e9fefcb8eddb599275..78a1f7a1499be84f15b94d75b30266dfb8c720ce 100644 (file)
@@ -976,6 +976,9 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx)
        struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
        u32 status, isp_err;
 
+       if (!rkisp1->irqs_enabled)
+               return IRQ_NONE;
+
        status = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS);
        if (!status)
                return IRQ_NONE;
index 2afe67ffa285e3755f35c5842827160b93f573b5..74d69ce22a33e801762bc156c8c40289b2b2d4cb 100644 (file)
@@ -319,6 +319,7 @@ config IR_PWM_TX
        tristate "PWM IR transmitter"
        depends on LIRC
        depends on PWM
+       depends on HIGH_RES_TIMERS
        depends on OF
        help
           Say Y if you want to use a PWM based IR transmitter. This is
index fe17c7f98e8101afdae3d608ab12a2ef7f971d0e..52d82cbe7685f5b5adadf4448a171fcb146612b8 100644 (file)
@@ -253,7 +253,7 @@ int lirc_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
        if (attr->attach_flags)
                return -EINVAL;
 
-       rcdev = rc_dev_get_from_fd(attr->target_fd);
+       rcdev = rc_dev_get_from_fd(attr->target_fd, true);
        if (IS_ERR(rcdev))
                return PTR_ERR(rcdev);
 
@@ -278,7 +278,7 @@ int lirc_prog_detach(const union bpf_attr *attr)
        if (IS_ERR(prog))
                return PTR_ERR(prog);
 
-       rcdev = rc_dev_get_from_fd(attr->target_fd);
+       rcdev = rc_dev_get_from_fd(attr->target_fd, true);
        if (IS_ERR(rcdev)) {
                bpf_prog_put(prog);
                return PTR_ERR(rcdev);
@@ -303,7 +303,7 @@ int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
        if (attr->query.query_flags)
                return -EINVAL;
 
-       rcdev = rc_dev_get_from_fd(attr->query.target_fd);
+       rcdev = rc_dev_get_from_fd(attr->query.target_fd, false);
        if (IS_ERR(rcdev))
                return PTR_ERR(rcdev);
 
index 1968067092594979942f030af29bf4b484b5fd09..69e630d85262f65f413ee8c9d092ea85cee01c91 100644 (file)
@@ -332,6 +332,7 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count)
                            sizeof(COMMAND_SMODE_EXIT), STATE_COMMAND_NO_RESP);
        if (err) {
                dev_err(irtoy->dev, "exit sample mode: %d\n", err);
+               kfree(buf);
                return err;
        }
 
@@ -339,6 +340,7 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count)
                            sizeof(COMMAND_SMODE_ENTER), STATE_COMMAND);
        if (err) {
                dev_err(irtoy->dev, "enter sample mode: %d\n", err);
+               kfree(buf);
                return err;
        }
 
index a537734832c5080498d263428a96d7b1d13dcb88..caad59f76793f750f757c8fe5e58fe569b6b4322 100644 (file)
@@ -814,7 +814,7 @@ void __exit lirc_dev_exit(void)
        unregister_chrdev_region(lirc_base_dev, RC_DEV_MAX);
 }
 
-struct rc_dev *rc_dev_get_from_fd(int fd)
+struct rc_dev *rc_dev_get_from_fd(int fd, bool write)
 {
        struct fd f = fdget(fd);
        struct lirc_fh *fh;
@@ -828,6 +828,9 @@ struct rc_dev *rc_dev_get_from_fd(int fd)
                return ERR_PTR(-EINVAL);
        }
 
+       if (write && !(f.file->f_mode & FMODE_WRITE))
+               return ERR_PTR(-EPERM);
+
        fh = f.file->private_data;
        dev = fh->rc;
 
index ef1e95e1af7fcccda49324e375b940cc92c627f2..7df949fc65e2b68bf88c12643410330fc1ad4635 100644 (file)
@@ -325,7 +325,7 @@ void lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev);
 void lirc_scancode_event(struct rc_dev *dev, struct lirc_scancode *lsc);
 int lirc_register(struct rc_dev *dev);
 void lirc_unregister(struct rc_dev *dev);
-struct rc_dev *rc_dev_get_from_fd(int fd);
+struct rc_dev *rc_dev_get_from_fd(int fd, bool write);
 #else
 static inline int lirc_dev_init(void) { return 0; }
 static inline void lirc_dev_exit(void) {}
index 2a2d949a9344ea78b540337d471996f2ec77d53e..39f45c2b6de8a885e12af08f302d8bc2dce15d61 100644 (file)
@@ -75,11 +75,15 @@ EXPORT_SYMBOL(mmc_gpio_set_cd_irq);
 int mmc_gpio_get_ro(struct mmc_host *host)
 {
        struct mmc_gpio *ctx = host->slot.handler_priv;
+       int cansleep;
 
        if (!ctx || !ctx->ro_gpio)
                return -ENOSYS;
 
-       return gpiod_get_value_cansleep(ctx->ro_gpio);
+       cansleep = gpiod_cansleep(ctx->ro_gpio);
+       return cansleep ?
+               gpiod_get_value_cansleep(ctx->ro_gpio) :
+               gpiod_get_value(ctx->ro_gpio);
 }
 EXPORT_SYMBOL(mmc_gpio_get_ro);
 
index 7bfee28116af12ebdf08efb7b0e51e68cb602956..d4a02184784a3458b55b601d1fba1216e1ef3149 100644 (file)
@@ -693,6 +693,35 @@ static int sdhci_pci_o2_init_sd_express(struct mmc_host *mmc, struct mmc_ios *io
        return 0;
 }
 
+static void sdhci_pci_o2_set_power(struct sdhci_host *host, unsigned char mode,  unsigned short vdd)
+{
+       struct sdhci_pci_chip *chip;
+       struct sdhci_pci_slot *slot = sdhci_priv(host);
+       u32 scratch_32 = 0;
+       u8 scratch_8 = 0;
+
+       chip = slot->chip;
+
+       if (mode == MMC_POWER_OFF) {
+               /* UnLock WP */
+               pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
+               scratch_8 &= 0x7f;
+               pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
+
+               /* Set PCR 0x354[16] to switch Clock Source back to OPE Clock */
+               pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32);
+               scratch_32 &= ~(O2_SD_SEL_DLL);
+               pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32);
+
+               /* Lock WP */
+               pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
+               scratch_8 |= 0x80;
+               pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
+       }
+
+       sdhci_set_power(host, mode, vdd);
+}
+
 static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 {
        struct sdhci_pci_chip *chip;
@@ -1051,6 +1080,7 @@ static const struct sdhci_ops sdhci_pci_o2_ops = {
        .set_bus_width = sdhci_set_bus_width,
        .reset = sdhci_reset,
        .set_uhs_signaling = sdhci_set_uhs_signaling,
+       .set_power = sdhci_pci_o2_set_power,
 };
 
 const struct sdhci_pci_fixes sdhci_o2 = {
index 8c651fdee039aab85019b9a574b813c51aa04ef6..57f1729066f28b76de26bd3c5145cbe6bcc2f9ac 100644 (file)
@@ -186,4 +186,5 @@ static void __exit arcnet_raw_exit(void)
 module_init(arcnet_raw_init);
 module_exit(arcnet_raw_exit);
 
+MODULE_DESCRIPTION("ARCnet raw mode packet interface module");
 MODULE_LICENSE("GPL");
index 8c3ccc7c83cd3cd92e73c44ebd09a6fa8f8c0c41..53d10a04d1bd0a765e34dd6e56217a59d5485cc9 100644 (file)
@@ -312,6 +312,7 @@ module_param(node, int, 0);
 module_param(io, int, 0);
 module_param(irq, int, 0);
 module_param_string(device, device, sizeof(device), 0);
+MODULE_DESCRIPTION("ARCnet COM90xx RIM I chipset driver");
 MODULE_LICENSE("GPL");
 
 static struct net_device *my_dev;
index c09b567845e1eeb025eff26c77ad5e22f6db150f..7a0a799737698f8ebb834b592d86c849aaf8f371 100644 (file)
@@ -265,4 +265,5 @@ static void __exit capmode_module_exit(void)
 module_init(capmode_module_init);
 module_exit(capmode_module_exit);
 
+MODULE_DESCRIPTION("ARCnet CAP mode packet interface module");
 MODULE_LICENSE("GPL");
index 7b5c8bb02f11941f6210200c23ee2f74272d49a3..c5e571ec94c990d0a76a19e3ab418730548c0ce1 100644 (file)
@@ -61,6 +61,7 @@ module_param(timeout, int, 0);
 module_param(backplane, int, 0);
 module_param(clockp, int, 0);
 module_param(clockm, int, 0);
+MODULE_DESCRIPTION("ARCnet COM20020 chipset PCI driver");
 MODULE_LICENSE("GPL");
 
 static void led_tx_set(struct led_classdev *led_cdev,
index 06e1651b594ba813fc5a0d75931c12ec299c100a..a0053e3992a364ef3e1d3c4328b4baf8956d248d 100644 (file)
@@ -399,6 +399,7 @@ EXPORT_SYMBOL(com20020_found);
 EXPORT_SYMBOL(com20020_netdev_ops);
 #endif
 
+MODULE_DESCRIPTION("ARCnet COM20020 chipset core driver");
 MODULE_LICENSE("GPL");
 
 #ifdef MODULE
index dc3253b318dafc3e668df035880a8bccabeb0fdc..75f08aa7528b4620180da471e87e225a39fcd06b 100644 (file)
@@ -97,6 +97,7 @@ module_param(backplane, int, 0);
 module_param(clockp, int, 0);
 module_param(clockm, int, 0);
 
+MODULE_DESCRIPTION("ARCnet COM20020 chipset PCMCIA driver");
 MODULE_LICENSE("GPL");
 
 /*====================================================================*/
index 37b47749fc8b4afb24ae60151ac5b316554ab391..3b463fbc6402114322278a6648a422f4a7ea2bff 100644 (file)
@@ -350,6 +350,7 @@ static char device[9];              /* use eg. device=arc1 to change name */
 module_param_hw(io, int, ioport, 0);
 module_param_hw(irq, int, irq, 0);
 module_param_string(device, device, sizeof(device), 0);
+MODULE_DESCRIPTION("ARCnet COM90xx IO mapped chipset driver");
 MODULE_LICENSE("GPL");
 
 #ifndef MODULE
index f49dae1942846d866d11aad4d619202fd7a8cb01..b3b287c1656179b6656d62a53e488ffcd85178ac 100644 (file)
@@ -645,6 +645,7 @@ static void com90xx_copy_from_card(struct net_device *dev, int bufnum,
        TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
 }
 
+MODULE_DESCRIPTION("ARCnet COM90xx normal chipset driver");
 MODULE_LICENSE("GPL");
 
 static int __init com90xx_init(void)
index a7752a5b647fcd4128e3e0c7b59961ad0a83c660..46519ca63a0aa5459732fd140d62ad679bc3a519 100644 (file)
@@ -78,6 +78,7 @@ static void __exit arcnet_rfc1051_exit(void)
 module_init(arcnet_rfc1051_init);
 module_exit(arcnet_rfc1051_exit);
 
+MODULE_DESCRIPTION("ARCNet packet format (RFC 1051) module");
 MODULE_LICENSE("GPL");
 
 /* Determine a packet's protocol ID.
index a4c856282674b3d3d74007f43fb7c7272ea046b8..0edf35d971c56ef15a11814167a2100927975f61 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "arcdevice.h"
 
+MODULE_DESCRIPTION("ARCNet packet format (RFC 1201) module");
 MODULE_LICENSE("GPL");
 
 static __be16 type_trans(struct sk_buff *skb, struct net_device *dev);
index 4e0600c7b050f21c82a8862e224bb055e95d5039..a11748b8d69b435cf97971cec21c0340365ed6d1 100644 (file)
@@ -1819,6 +1819,8 @@ void bond_xdp_set_features(struct net_device *bond_dev)
        bond_for_each_slave(bond, slave, iter)
                val &= slave->dev->xdp_features;
 
+       val &= ~NETDEV_XDP_ACT_XSK_ZEROCOPY;
+
        xdp_set_features_flag(bond_dev, val);
 }
 
@@ -5909,9 +5911,6 @@ void bond_setup(struct net_device *bond_dev)
        if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP)
                bond_dev->features |= BOND_XFRM_FEATURES;
 #endif /* CONFIG_XFRM_OFFLOAD */
-
-       if (bond_xdp_check(bond))
-               bond_dev->xdp_features = NETDEV_XDP_ACT_MASK;
 }
 
 /* Destroy a bonding device.
index 036d85ef07f5ba676611e4a20ea470ab7691ffc1..dfdc039d92a6c114a1d5204c3a42ad170ca1b400 100644 (file)
@@ -346,7 +346,7 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
                        /* Neither of TDC parameters nor TDC flags are
                         * provided: do calculation
                         */
-                       can_calc_tdco(&priv->tdc, priv->tdc_const, &priv->data_bittiming,
+                       can_calc_tdco(&priv->tdc, priv->tdc_const, &dbt,
                                      &priv->ctrlmode, priv->ctrlmode_supported);
                } /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly
                   * turned off. TDC is disabled: do nothing
index 237066d307044583167923fcfc54d88a1ff53bc4..14ca42491512c62d71dac84e6e7d4dd91b2eb19b 100644 (file)
@@ -32,4 +32,5 @@ static int __init dsa_loop_bdinfo_init(void)
 }
 arch_initcall(dsa_loop_bdinfo_init)
 
+MODULE_DESCRIPTION("DSA mock-up switch driver");
 MODULE_LICENSE("GPL");
index cdbf053b5376c51c91deadb0d9ce6ab752b90745..0050c5894563b8a54c21a6b8933b844d63804098 100644 (file)
@@ -451,6 +451,9 @@ static void pdsc_remove(struct pci_dev *pdev)
 
 static void pdsc_stop_health_thread(struct pdsc *pdsc)
 {
+       if (pdsc->pdev->is_virtfn)
+               return;
+
        timer_shutdown_sync(&pdsc->wdtimer);
        if (pdsc->health_work.func)
                cancel_work_sync(&pdsc->health_work);
@@ -458,6 +461,9 @@ static void pdsc_stop_health_thread(struct pdsc *pdsc)
 
 static void pdsc_restart_health_thread(struct pdsc *pdsc)
 {
+       if (pdsc->pdev->is_virtfn)
+               return;
+
        timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
        mod_timer(&pdsc->wdtimer, jiffies + 1);
 }
index abd4832e4ed21f3c2a22aed047a0331675162907..5acb3e16b5677b7826e488942ff6efb2c3cdf400 100644 (file)
@@ -993,7 +993,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
        return 0;
 
 err_exit_hwts_rx:
-       aq_ring_free(&aq_ptp->hwts_rx);
+       aq_ring_hwts_rx_free(&aq_ptp->hwts_rx);
 err_exit_ptp_rx:
        aq_ring_free(&aq_ptp->ptp_rx);
 err_exit_ptp_tx:
@@ -1011,7 +1011,7 @@ void aq_ptp_ring_free(struct aq_nic_s *aq_nic)
 
        aq_ring_free(&aq_ptp->ptp_tx);
        aq_ring_free(&aq_ptp->ptp_rx);
-       aq_ring_free(&aq_ptp->hwts_rx);
+       aq_ring_hwts_rx_free(&aq_ptp->hwts_rx);
 
        aq_ptp_skb_ring_release(&aq_ptp->skb_ring);
 }
index cda8597b4e1469d2895f895f982f84cb97ef4506..f7433abd659159203f99fbb6cc9ed394bdedacfc 100644 (file)
@@ -919,6 +919,19 @@ void aq_ring_free(struct aq_ring_s *self)
        }
 }
 
+void aq_ring_hwts_rx_free(struct aq_ring_s *self)
+{
+       if (!self)
+               return;
+
+       if (self->dx_ring) {
+               dma_free_coherent(aq_nic_get_dev(self->aq_nic),
+                                 self->size * self->dx_size + AQ_CFG_RXDS_DEF,
+                                 self->dx_ring, self->dx_ring_pa);
+               self->dx_ring = NULL;
+       }
+}
+
 unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data)
 {
        unsigned int count;
index 52847310740a21097dfc35a395e96dfe5de46321..d627ace850ff54201b760a079416e4d690e73184 100644 (file)
@@ -210,6 +210,7 @@ int aq_ring_rx_fill(struct aq_ring_s *self);
 int aq_ring_hwts_rx_alloc(struct aq_ring_s *self,
                          struct aq_nic_s *aq_nic, unsigned int idx,
                          unsigned int size, unsigned int dx_size);
+void aq_ring_hwts_rx_free(struct aq_ring_s *self);
 void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic);
 
 unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data);
index 53e5428812552b56de4c7809c5c3f49f7c65379b..f59557b0cd51523896890ffe6121ffbac54f5f70 100644 (file)
@@ -684,6 +684,8 @@ static int bcmasp_init_rx(struct bcmasp_intf *intf)
 
        intf->rx_buf_order = get_order(RING_BUFFER_SIZE);
        buffer_pg = alloc_pages(GFP_KERNEL, intf->rx_buf_order);
+       if (!buffer_pg)
+               return -ENOMEM;
 
        dma = dma_map_page(kdev, buffer_pg, 0, RING_BUFFER_SIZE,
                           DMA_FROM_DEVICE);
@@ -1092,6 +1094,7 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect)
        return 0;
 
 err_reclaim_tx:
+       netif_napi_del(&intf->tx_napi);
        bcmasp_reclaim_free_all_tx(intf);
 err_phy_disconnect:
        if (phydev)
index 31191b520b5875a72f08e22ce316a103ccee68ea..c32174484a967ae4cf49f6025bf0892333d1fd89 100644 (file)
@@ -1091,10 +1091,10 @@ bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx)
  * Free all TxQs buffers and then notify TX_E_CLEANUP_DONE to Tx fsm.
  */
 static void
-bnad_tx_cleanup(struct delayed_work *work)
+bnad_tx_cleanup(struct work_struct *work)
 {
        struct bnad_tx_info *tx_info =
-               container_of(work, struct bnad_tx_info, tx_cleanup_work);
+               container_of(work, struct bnad_tx_info, tx_cleanup_work.work);
        struct bnad *bnad = NULL;
        struct bna_tcb *tcb;
        unsigned long flags;
@@ -1170,7 +1170,7 @@ bnad_cb_rx_stall(struct bnad *bnad, struct bna_rx *rx)
  * Free all RxQs buffers and then notify RX_E_CLEANUP_DONE to Rx fsm.
  */
 static void
-bnad_rx_cleanup(void *work)
+bnad_rx_cleanup(struct work_struct *work)
 {
        struct bnad_rx_info *rx_info =
                container_of(work, struct bnad_rx_info, rx_cleanup_work);
@@ -1991,8 +1991,7 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
        }
        tx_info->tx = tx;
 
-       INIT_DELAYED_WORK(&tx_info->tx_cleanup_work,
-                       (work_func_t)bnad_tx_cleanup);
+       INIT_DELAYED_WORK(&tx_info->tx_cleanup_work, bnad_tx_cleanup);
 
        /* Register ISR for the Tx object */
        if (intr_info->intr_type == BNA_INTR_T_MSIX) {
@@ -2248,8 +2247,7 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
        rx_info->rx = rx;
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
-       INIT_WORK(&rx_info->rx_cleanup_work,
-                       (work_func_t)(bnad_rx_cleanup));
+       INIT_WORK(&rx_info->rx_cleanup_work, bnad_rx_cleanup);
 
        /*
         * Init NAPI, so that state is set to NAPI_STATE_SCHED,
index 9aeff2b37a61299587c22dc39b207204c3412543..64eadd3207983a671332d47cc4fdc966561d8425 100644 (file)
@@ -719,17 +719,25 @@ static void tsnep_xdp_xmit_flush(struct tsnep_tx *tx)
 
 static bool tsnep_xdp_xmit_back(struct tsnep_adapter *adapter,
                                struct xdp_buff *xdp,
-                               struct netdev_queue *tx_nq, struct tsnep_tx *tx)
+                               struct netdev_queue *tx_nq, struct tsnep_tx *tx,
+                               bool zc)
 {
        struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp);
        bool xmit;
+       u32 type;
 
        if (unlikely(!xdpf))
                return false;
 
+       /* no page pool for zero copy */
+       if (zc)
+               type = TSNEP_TX_TYPE_XDP_NDO;
+       else
+               type = TSNEP_TX_TYPE_XDP_TX;
+
        __netif_tx_lock(tx_nq, smp_processor_id());
 
-       xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, TSNEP_TX_TYPE_XDP_TX);
+       xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, type);
 
        /* Avoid transmit queue timeout since we share it with the slow path */
        if (xmit)
@@ -1273,7 +1281,7 @@ static bool tsnep_xdp_run_prog(struct tsnep_rx *rx, struct bpf_prog *prog,
        case XDP_PASS:
                return false;
        case XDP_TX:
-               if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx))
+               if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, false))
                        goto out_failure;
                *status |= TSNEP_XDP_TX;
                return true;
@@ -1323,7 +1331,7 @@ static bool tsnep_xdp_run_prog_zc(struct tsnep_rx *rx, struct bpf_prog *prog,
        case XDP_PASS:
                return false;
        case XDP_TX:
-               if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx))
+               if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, true))
                        goto out_failure;
                *status |= TSNEP_XDP_TX;
                return true;
index 9d88ed6105fd8f25ac8724827a9467f5043ee8b5..8db1eb0c1768c9869d7bf09820b4324b91bf788c 100644 (file)
@@ -1523,7 +1523,7 @@ void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share,
                reg = rd32(hw, I40E_PRTDCB_RETSTCC(i));
                reg &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK     |
                         I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK |
-                        I40E_PRTDCB_RETSTCC_ETSTC_SHIFT);
+                        I40E_PRTDCB_RETSTCC_ETSTC_MASK);
                reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_BWSHARE_MASK,
                                  bw_share[i]);
                reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK,
index 6b60dc9b77361a2537466c18c8d78eafbc35a01a..d76497566e40e739fd7eba7773fbb84c02ddf93b 100644 (file)
@@ -43,7 +43,7 @@
 #define I40E_LLDP_TLV_SUBTYPE_SHIFT    0
 #define I40E_LLDP_TLV_SUBTYPE_MASK     (0xFF << I40E_LLDP_TLV_SUBTYPE_SHIFT)
 #define I40E_LLDP_TLV_OUI_SHIFT                8
-#define I40E_LLDP_TLV_OUI_MASK         (0xFFFFFF << I40E_LLDP_TLV_OUI_SHIFT)
+#define I40E_LLDP_TLV_OUI_MASK         (0xFFFFFFU << I40E_LLDP_TLV_OUI_SHIFT)
 
 /* Defines for IEEE ETS TLV */
 #define I40E_IEEE_ETS_MAXTC_SHIFT      0
index 6e7fd473abfd001eb45e8b5bda8978fff9eec26b..54eb55464e3151f00665f9b780c65a1861f8ca07 100644 (file)
@@ -4926,27 +4926,23 @@ int i40e_vsi_start_rings(struct i40e_vsi *vsi)
 void i40e_vsi_stop_rings(struct i40e_vsi *vsi)
 {
        struct i40e_pf *pf = vsi->back;
-       int pf_q, err, q_end;
+       u32 pf_q, tx_q_end, rx_q_end;
 
        /* When port TX is suspended, don't wait */
        if (test_bit(__I40E_PORT_SUSPENDED, vsi->back->state))
                return i40e_vsi_stop_rings_no_wait(vsi);
 
-       q_end = vsi->base_queue + vsi->num_queue_pairs;
-       for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++)
-               i40e_pre_tx_queue_cfg(&pf->hw, (u32)pf_q, false);
+       tx_q_end = vsi->base_queue +
+               vsi->alloc_queue_pairs * (i40e_enabled_xdp_vsi(vsi) ? 2 : 1);
+       for (pf_q = vsi->base_queue; pf_q < tx_q_end; pf_q++)
+               i40e_pre_tx_queue_cfg(&pf->hw, pf_q, false);
 
-       for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++) {
-               err = i40e_control_wait_rx_q(pf, pf_q, false);
-               if (err)
-                       dev_info(&pf->pdev->dev,
-                                "VSI seid %d Rx ring %d disable timeout\n",
-                                vsi->seid, pf_q);
-       }
+       rx_q_end = vsi->base_queue + vsi->num_queue_pairs;
+       for (pf_q = vsi->base_queue; pf_q < rx_q_end; pf_q++)
+               i40e_control_rx_q(pf, pf_q, false);
 
        msleep(I40E_DISABLE_TX_GAP_MSEC);
-       pf_q = vsi->base_queue;
-       for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++)
+       for (pf_q = vsi->base_queue; pf_q < tx_q_end; pf_q++)
                wr32(&pf->hw, I40E_QTX_ENA(pf_q), 0);
 
        i40e_vsi_wait_queues_disabled(vsi);
@@ -5360,7 +5356,7 @@ static int i40e_pf_wait_queues_disabled(struct i40e_pf *pf)
 {
        int v, ret = 0;
 
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                if (pf->vsi[v]) {
                        ret = i40e_vsi_wait_queues_disabled(pf->vsi[v]);
                        if (ret)
index 908cdbd3ec5d4fafe26fa03b4a41433f04ef5d31..b34c7177088745468ad33817302a631a5162322a 100644 (file)
@@ -2848,6 +2848,24 @@ error_param:
                                      (u8 *)&stats, sizeof(stats));
 }
 
+/**
+ * i40e_can_vf_change_mac
+ * @vf: pointer to the VF info
+ *
+ * Return true if the VF is allowed to change its MAC filters, false otherwise
+ */
+static bool i40e_can_vf_change_mac(struct i40e_vf *vf)
+{
+       /* If the VF MAC address has been set administratively (via the
+        * ndo_set_vf_mac command), then deny permission to the VF to
+        * add/delete unicast MAC addresses, unless the VF is trusted
+        */
+       if (vf->pf_set_mac && !vf->trusted)
+               return false;
+
+       return true;
+}
+
 #define I40E_MAX_MACVLAN_PER_HW 3072
 #define I40E_MAX_MACVLAN_PER_PF(num_ports) (I40E_MAX_MACVLAN_PER_HW /  \
        (num_ports))
@@ -2907,8 +2925,8 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
                 * The VF may request to set the MAC address filter already
                 * assigned to it so do not return an error in that case.
                 */
-               if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
-                   !is_multicast_ether_addr(addr) && vf->pf_set_mac &&
+               if (!i40e_can_vf_change_mac(vf) &&
+                   !is_multicast_ether_addr(addr) &&
                    !ether_addr_equal(addr, vf->default_lan_addr.addr)) {
                        dev_err(&pf->pdev->dev,
                                "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n");
@@ -3114,19 +3132,29 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
                        ret = -EINVAL;
                        goto error_param;
                }
-               if (ether_addr_equal(al->list[i].addr, vf->default_lan_addr.addr))
-                       was_unimac_deleted = true;
        }
        vsi = pf->vsi[vf->lan_vsi_idx];
 
        spin_lock_bh(&vsi->mac_filter_hash_lock);
        /* delete addresses from the list */
-       for (i = 0; i < al->num_elements; i++)
+       for (i = 0; i < al->num_elements; i++) {
+               const u8 *addr = al->list[i].addr;
+
+               /* Allow to delete VF primary MAC only if it was not set
+                * administratively by PF or if VF is trusted.
+                */
+               if (ether_addr_equal(addr, vf->default_lan_addr.addr) &&
+                   i40e_can_vf_change_mac(vf))
+                       was_unimac_deleted = true;
+               else
+                       continue;
+
                if (i40e_del_mac_filter(vsi, al->list[i].addr)) {
                        ret = -EINVAL;
                        spin_unlock_bh(&vsi->mac_filter_hash_lock);
                        goto error_param;
                }
+       }
 
        spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
index 2a25323105e5b9bd5a1dbf072f097ddd90872210..467372d541d21f9c26416275f945b12e684079ef 100644 (file)
@@ -151,6 +151,27 @@ ice_lag_find_hw_by_lport(struct ice_lag *lag, u8 lport)
        return NULL;
 }
 
+/**
+ * ice_pkg_has_lport_extract - check if lport extraction supported
+ * @hw: HW struct
+ */
+static bool ice_pkg_has_lport_extract(struct ice_hw *hw)
+{
+       int i;
+
+       for (i = 0; i < hw->blk[ICE_BLK_SW].es.count; i++) {
+               u16 offset;
+               u8 fv_prot;
+
+               ice_find_prot_off(hw, ICE_BLK_SW, ICE_SW_DEFAULT_PROFILE, i,
+                                 &fv_prot, &offset);
+               if (fv_prot == ICE_FV_PROT_MDID &&
+                   offset == ICE_LP_EXT_BUF_OFFSET)
+                       return true;
+       }
+       return false;
+}
+
 /**
  * ice_lag_find_primary - returns pointer to primary interfaces lag struct
  * @lag: local interfaces lag struct
@@ -1206,7 +1227,7 @@ static void ice_lag_del_prune_list(struct ice_lag *lag, struct ice_pf *event_pf)
 }
 
 /**
- * ice_lag_init_feature_support_flag - Check for NVM support for LAG
+ * ice_lag_init_feature_support_flag - Check for package and NVM support for LAG
  * @pf: PF struct
  */
 static void ice_lag_init_feature_support_flag(struct ice_pf *pf)
@@ -1219,7 +1240,7 @@ static void ice_lag_init_feature_support_flag(struct ice_pf *pf)
        else
                ice_clear_feature_support(pf, ICE_F_ROCE_LAG);
 
-       if (caps->sriov_lag)
+       if (caps->sriov_lag && ice_pkg_has_lport_extract(&pf->hw))
                ice_set_feature_support(pf, ICE_F_SRIOV_LAG);
        else
                ice_clear_feature_support(pf, ICE_F_SRIOV_LAG);
index ede833dfa65866da00d8f4a6d77a90470906f863..183b38792ef22d9ac54daa0ea4a8156039681e7c 100644 (file)
@@ -17,6 +17,9 @@ enum ice_lag_role {
 #define ICE_LAG_INVALID_PORT 0xFF
 
 #define ICE_LAG_RESET_RETRIES          5
+#define ICE_SW_DEFAULT_PROFILE         0
+#define ICE_FV_PROT_MDID               255
+#define ICE_LP_EXT_BUF_OFFSET          32
 
 struct ice_pf;
 struct ice_vf;
index 82bc54fec7f36400a9be1f6603da2770ab5bb2e5..a2562f04267f23695af92be0bca5c1174702bef3 100644 (file)
@@ -24,7 +24,7 @@
 #define rd64(a, reg)           readq((a)->hw_addr + (reg))
 
 #define ice_flush(a)           rd32((a), GLGEN_STAT)
-#define ICE_M(m, s)            ((m) << (s))
+#define ICE_M(m, s)            ((m ## U) << (s))
 
 struct ice_dma_mem {
        void *va;
index 41ab6d7bbd9ef923fb766555ba48c5533e989f93..a508e917ce5ffab9e092a62337fbe70b27efbc5e 100644 (file)
@@ -1072,7 +1072,7 @@ struct ice_aq_get_set_rss_lut_params {
 #define ICE_OROM_VER_BUILD_SHIFT       8
 #define ICE_OROM_VER_BUILD_MASK                (0xffff << ICE_OROM_VER_BUILD_SHIFT)
 #define ICE_OROM_VER_SHIFT             24
-#define ICE_OROM_VER_MASK              (0xff << ICE_OROM_VER_SHIFT)
+#define ICE_OROM_VER_MASK              (0xffU << ICE_OROM_VER_SHIFT)
 #define ICE_SR_PFA_PTR                 0x40
 #define ICE_SR_1ST_NVM_BANK_PTR                0x42
 #define ICE_SR_NVM_BANK_SIZE           0x43
index a2b759531cb7ba44720f000018597d5222bec900..3c2dc7bdebb50eb9f08ec49ce6590f2b35445e53 100644 (file)
@@ -637,7 +637,7 @@ struct igb_adapter {
                struct timespec64 period;
        } perout[IGB_N_PEROUT];
 
-       char fw_version[32];
+       char fw_version[48];
 #ifdef CONFIG_IGB_HWMON
        struct hwmon_buff *igb_hwmon_buff;
        bool ets;
index 4df8d4153aa5f5ce7ac9dd566180d552be9f5b4f..cebb44f51d5f5bbd1177b0caeb1e08f7a2fc30db 100644 (file)
@@ -3069,7 +3069,6 @@ void igb_set_fw_version(struct igb_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
        struct e1000_fw_version fw;
-       char *lbuf;
 
        igb_get_fw_version(hw, &fw);
 
@@ -3077,34 +3076,36 @@ void igb_set_fw_version(struct igb_adapter *adapter)
        case e1000_i210:
        case e1000_i211:
                if (!(igb_get_flash_presence_i210(hw))) {
-                       lbuf = kasprintf(GFP_KERNEL, "%2d.%2d-%d",
-                                        fw.invm_major, fw.invm_minor,
-                                        fw.invm_img_type);
+                       snprintf(adapter->fw_version,
+                                sizeof(adapter->fw_version),
+                                "%2d.%2d-%d",
+                                fw.invm_major, fw.invm_minor,
+                                fw.invm_img_type);
                        break;
                }
                fallthrough;
        default:
                /* if option rom is valid, display its version too */
                if (fw.or_valid) {
-                       lbuf = kasprintf(GFP_KERNEL, "%d.%d, 0x%08x, %d.%d.%d",
-                                        fw.eep_major, fw.eep_minor,
-                                        fw.etrack_id, fw.or_major, fw.or_build,
-                                        fw.or_patch);
+                       snprintf(adapter->fw_version,
+                                sizeof(adapter->fw_version),
+                                "%d.%d, 0x%08x, %d.%d.%d",
+                                fw.eep_major, fw.eep_minor, fw.etrack_id,
+                                fw.or_major, fw.or_build, fw.or_patch);
                /* no option rom */
                } else if (fw.etrack_id != 0X0000) {
-                       lbuf = kasprintf(GFP_KERNEL, "%d.%d, 0x%08x",
-                                        fw.eep_major, fw.eep_minor,
-                                        fw.etrack_id);
+                       snprintf(adapter->fw_version,
+                                sizeof(adapter->fw_version),
+                                "%d.%d, 0x%08x",
+                                fw.eep_major, fw.eep_minor, fw.etrack_id);
                } else {
-                       lbuf = kasprintf(GFP_KERNEL, "%d.%d.%d", fw.eep_major,
-                                        fw.eep_minor, fw.eep_build);
+                       snprintf(adapter->fw_version,
+                                sizeof(adapter->fw_version),
+                                "%d.%d.%d",
+                                fw.eep_major, fw.eep_minor, fw.eep_build);
                }
                break;
        }
-
-       /* the truncate happens here if it doesn't fit */
-       strscpy(adapter->fw_version, lbuf, sizeof(adapter->fw_version));
-       kfree(lbuf);
 }
 
 /**
index 7cd8716d2ffa3a90b35cea6218922a8cf656b9eb..861f37076861655df235fed77f6e7d0cb4bb3dc4 100644 (file)
@@ -130,11 +130,7 @@ void igc_power_down_phy_copper(struct igc_hw *hw)
        /* The PHY will retain its settings across a power down/up cycle */
        hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
        mii_reg |= MII_CR_POWER_DOWN;
-
-       /* Temporary workaround - should be removed when PHY will implement
-        * IEEE registers as properly
-        */
-       /* hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);*/
+       hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
        usleep_range(1000, 2000);
 }
 
index 167145bdcb75d3f852134fcaa44fc2f307c42478..e5d6156655ba48ee607c531e7c8951aa32d6e117 100644 (file)
@@ -61,28 +61,6 @@ int rvu_npc_get_tx_nibble_cfg(struct rvu *rvu, u64 nibble_ena)
        return 0;
 }
 
-static int npc_mcam_verify_pf_func(struct rvu *rvu,
-                                  struct mcam_entry *entry_data, u8 intf,
-                                  u16 pcifunc)
-{
-       u16 pf_func, pf_func_mask;
-
-       if (is_npc_intf_rx(intf))
-               return 0;
-
-       pf_func_mask = (entry_data->kw_mask[0] >> 32) &
-               NPC_KEX_PF_FUNC_MASK;
-       pf_func = (entry_data->kw[0] >> 32) & NPC_KEX_PF_FUNC_MASK;
-
-       pf_func = be16_to_cpu((__force __be16)pf_func);
-       if (pf_func_mask != NPC_KEX_PF_FUNC_MASK ||
-           ((pf_func & ~RVU_PFVF_FUNC_MASK) !=
-            (pcifunc & ~RVU_PFVF_FUNC_MASK)))
-               return -EINVAL;
-
-       return 0;
-}
-
 void rvu_npc_set_pkind(struct rvu *rvu, int pkind, struct rvu_pfvf *pfvf)
 {
        int blkaddr;
@@ -1850,8 +1828,8 @@ void npc_mcam_rsrcs_deinit(struct rvu *rvu)
 {
        struct npc_mcam *mcam = &rvu->hw->mcam;
 
-       kfree(mcam->bmap);
-       kfree(mcam->bmap_reverse);
+       bitmap_free(mcam->bmap);
+       bitmap_free(mcam->bmap_reverse);
        kfree(mcam->entry2pfvf_map);
        kfree(mcam->cntr2pfvf_map);
        kfree(mcam->entry2cntr_map);
@@ -1904,21 +1882,20 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
        mcam->pf_offset = mcam->nixlf_offset + nixlf_count;
 
        /* Allocate bitmaps for managing MCAM entries */
-       mcam->bmap = kmalloc_array(BITS_TO_LONGS(mcam->bmap_entries),
-                                  sizeof(long), GFP_KERNEL);
+       mcam->bmap = bitmap_zalloc(mcam->bmap_entries, GFP_KERNEL);
        if (!mcam->bmap)
                return -ENOMEM;
 
-       mcam->bmap_reverse = kmalloc_array(BITS_TO_LONGS(mcam->bmap_entries),
-                                          sizeof(long), GFP_KERNEL);
+       mcam->bmap_reverse = bitmap_zalloc(mcam->bmap_entries, GFP_KERNEL);
        if (!mcam->bmap_reverse)
                goto free_bmap;
 
        mcam->bmap_fcnt = mcam->bmap_entries;
 
        /* Alloc memory for saving entry to RVU PFFUNC allocation mapping */
-       mcam->entry2pfvf_map = kmalloc_array(mcam->bmap_entries,
-                                            sizeof(u16), GFP_KERNEL);
+       mcam->entry2pfvf_map = kcalloc(mcam->bmap_entries, sizeof(u16),
+                                      GFP_KERNEL);
+
        if (!mcam->entry2pfvf_map)
                goto free_bmap_reverse;
 
@@ -1941,21 +1918,21 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
        if (err)
                goto free_entry_map;
 
-       mcam->cntr2pfvf_map = kmalloc_array(mcam->counters.max,
-                                           sizeof(u16), GFP_KERNEL);
+       mcam->cntr2pfvf_map = kcalloc(mcam->counters.max, sizeof(u16),
+                                     GFP_KERNEL);
        if (!mcam->cntr2pfvf_map)
                goto free_cntr_bmap;
 
        /* Alloc memory for MCAM entry to counter mapping and for tracking
         * counter's reference count.
         */
-       mcam->entry2cntr_map = kmalloc_array(mcam->bmap_entries,
-                                            sizeof(u16), GFP_KERNEL);
+       mcam->entry2cntr_map = kcalloc(mcam->bmap_entries, sizeof(u16),
+                                      GFP_KERNEL);
        if (!mcam->entry2cntr_map)
                goto free_cntr_map;
 
-       mcam->cntr_refcnt = kmalloc_array(mcam->counters.max,
-                                         sizeof(u16), GFP_KERNEL);
+       mcam->cntr_refcnt = kcalloc(mcam->counters.max, sizeof(u16),
+                                   GFP_KERNEL);
        if (!mcam->cntr_refcnt)
                goto free_entry_cntr_map;
 
@@ -1988,9 +1965,9 @@ free_cntr_bmap:
 free_entry_map:
        kfree(mcam->entry2pfvf_map);
 free_bmap_reverse:
-       kfree(mcam->bmap_reverse);
+       bitmap_free(mcam->bmap_reverse);
 free_bmap:
-       kfree(mcam->bmap);
+       bitmap_free(mcam->bmap);
 
        return -ENOMEM;
 }
@@ -2852,12 +2829,6 @@ int rvu_mbox_handler_npc_mcam_write_entry(struct rvu *rvu,
        else
                nix_intf = pfvf->nix_rx_intf;
 
-       if (!is_pffunc_af(pcifunc) &&
-           npc_mcam_verify_pf_func(rvu, &req->entry_data, req->intf, pcifunc)) {
-               rc = NPC_MCAM_INVALID_REQ;
-               goto exit;
-       }
-
        /* For AF installed rules, the nix_intf should be set to target NIX */
        if (is_pffunc_af(req->hdr.pcifunc))
                nix_intf = req->intf;
@@ -3209,10 +3180,6 @@ int rvu_mbox_handler_npc_mcam_alloc_and_write_entry(struct rvu *rvu,
        if (!is_npc_interface_valid(rvu, req->intf))
                return NPC_MCAM_INVALID_REQ;
 
-       if (npc_mcam_verify_pf_func(rvu, &req->entry_data, req->intf,
-                                   req->hdr.pcifunc))
-               return NPC_MCAM_INVALID_REQ;
-
        /* Try to allocate a MCAM entry */
        entry_req.hdr.pcifunc = req->hdr.pcifunc;
        entry_req.contig = true;
index 7ca6941ea0b9b4d684ba45482b88db066a728f98..02d0b707aea5bd6b9dea286180914b5aaba4a51d 100644 (file)
@@ -951,8 +951,11 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
        if (pfvf->ptp && qidx < pfvf->hw.tx_queues) {
                err = qmem_alloc(pfvf->dev, &sq->timestamps, qset->sqe_cnt,
                                 sizeof(*sq->timestamps));
-               if (err)
+               if (err) {
+                       kfree(sq->sg);
+                       sq->sg = NULL;
                        return err;
+               }
        }
 
        sq->head = 0;
@@ -968,7 +971,14 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
        sq->stats.bytes = 0;
        sq->stats.pkts = 0;
 
-       return pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura);
+       err = pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura);
+       if (err) {
+               kfree(sq->sg);
+               sq->sg = NULL;
+               return err;
+       }
+
+       return 0;
 
 }
 
index 18fed2b34fb1cad6319f972ca5b6d604701bbce5..928bf24d4b123945afc9df29ea5d758792d269cb 100644 (file)
@@ -389,7 +389,7 @@ static void mlx5_dpll_remove(struct auxiliary_device *adev)
        struct mlx5_dpll *mdpll = auxiliary_get_drvdata(adev);
        struct mlx5_core_dev *mdev = mdpll->mdev;
 
-       cancel_delayed_work(&mdpll->work);
+       cancel_delayed_work_sync(&mdpll->work);
        mlx5_dpll_mdev_netdev_untrack(mdpll, mdev);
        destroy_workqueue(mdpll->wq);
        dpll_pin_unregister(mdpll->dpll, mdpll->dpll_pin,
index 41fa2523d91d3bf57479dd7d66c1903786aa98b2..5f2cd9a8cf8fb39cef3d6be0806f3a6f9b7cdac7 100644 (file)
@@ -37,19 +37,24 @@ static void lan966x_lag_set_aggr_pgids(struct lan966x *lan966x)
 
        /* Now, set PGIDs for each active LAG */
        for (lag = 0; lag < lan966x->num_phys_ports; ++lag) {
-               struct net_device *bond = lan966x->ports[lag]->bond;
+               struct lan966x_port *port = lan966x->ports[lag];
                int num_active_ports = 0;
+               struct net_device *bond;
                unsigned long bond_mask;
                u8 aggr_idx[16];
 
-               if (!bond || (visited & BIT(lag)))
+               if (!port || !port->bond || (visited & BIT(lag)))
                        continue;
 
+               bond = port->bond;
                bond_mask = lan966x_lag_get_mask(lan966x, bond);
 
                for_each_set_bit(p, &bond_mask, lan966x->num_phys_ports) {
                        struct lan966x_port *port = lan966x->ports[p];
 
+                       if (!port)
+                               continue;
+
                        lan_wr(ANA_PGID_PGID_SET(bond_mask),
                               lan966x, ANA_PGID(p));
                        if (port->lag_tx_active)
index e522845c7c211619a252bb995dec65160d7a1ae5..0d7d138d6e0d7e4f468f66683707cd22d750b64a 100644 (file)
@@ -1084,7 +1084,7 @@ nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev,
        u16 nfp_mac_idx = 0;
 
        entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr);
-       if (entry && nfp_tunnel_is_mac_idx_global(entry->index)) {
+       if (entry && (nfp_tunnel_is_mac_idx_global(entry->index) || netif_is_lag_port(netdev))) {
                if (entry->bridge_count ||
                    !nfp_flower_is_supported_bridge(netdev)) {
                        nfp_tunnel_offloaded_macs_inc_ref_and_link(entry,
index 3b3210d823e8038704391e085b9d7951031dd309..f28e769e6fdadab091d447f3de4cb8df1d2b4d3e 100644 (file)
@@ -2776,6 +2776,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
        case NFP_NFD_VER_NFD3:
                netdev->netdev_ops = &nfp_nfd3_netdev_ops;
                netdev->xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY;
+               netdev->xdp_features |= NETDEV_XDP_ACT_REDIRECT;
                break;
        case NFP_NFD_VER_NFDK:
                netdev->netdev_ops = &nfp_nfdk_netdev_ops;
index 33b4c28563162eeab3938da414b32cfd480c13d7..3f10c5365c80ebb2fe079b779fee644a46ed33da 100644 (file)
@@ -537,11 +537,13 @@ static int enable_bars(struct nfp6000_pcie *nfp, u16 interface)
        const u32 barcfg_msix_general =
                NFP_PCIE_BAR_PCIE2CPP_MapType(
                        NFP_PCIE_BAR_PCIE2CPP_MapType_GENERAL) |
-               NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT;
+               NFP_PCIE_BAR_PCIE2CPP_LengthSelect(
+                       NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT);
        const u32 barcfg_msix_xpb =
                NFP_PCIE_BAR_PCIE2CPP_MapType(
                        NFP_PCIE_BAR_PCIE2CPP_MapType_BULK) |
-               NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT |
+               NFP_PCIE_BAR_PCIE2CPP_LengthSelect(
+                       NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT) |
                NFP_PCIE_BAR_PCIE2CPP_Target_BaseAddress(
                        NFP_CPP_TARGET_ISLAND_XPB);
        const u32 barcfg_explicit[4] = {
index 54cd96b035d680a61297723b46adc16bf10ab3fa..6f47767598637ed3d2a961f6815cc183f066067b 100644 (file)
@@ -579,6 +579,9 @@ int ionic_tx_napi(struct napi_struct *napi, int budget)
        work_done = ionic_cq_service(cq, budget,
                                     ionic_tx_service, NULL, NULL);
 
+       if (unlikely(!budget))
+               return budget;
+
        if (work_done < budget && napi_complete_done(napi, work_done)) {
                ionic_dim_update(qcq, IONIC_LIF_F_TX_DIM_INTR);
                flags |= IONIC_INTR_CRED_UNMASK;
@@ -607,6 +610,9 @@ int ionic_rx_napi(struct napi_struct *napi, int budget)
        u32 work_done = 0;
        u32 flags = 0;
 
+       if (unlikely(!budget))
+               return budget;
+
        lif = cq->bound_q->lif;
        idev = &lif->ionic->idev;
 
@@ -656,6 +662,9 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget)
        tx_work_done = ionic_cq_service(txcq, IONIC_TX_BUDGET_DEFAULT,
                                        ionic_tx_service, NULL, NULL);
 
+       if (unlikely(!budget))
+               return budget;
+
        rx_work_done = ionic_cq_service(rxcq, budget,
                                        ionic_rx_service, NULL, NULL);
 
index 0e3731f50fc2873dc3c4c06c16ffe1f4a8707e83..f7566cfa45ca37a3cfd02331c24f49bf576393a7 100644 (file)
@@ -772,29 +772,25 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
        struct ravb_rx_desc *desc;
        struct sk_buff *skb;
        dma_addr_t dma_addr;
+       int rx_packets = 0;
        u8  desc_status;
-       int boguscnt;
        u16 pkt_len;
        u8  die_dt;
        int entry;
        int limit;
+       int i;
 
        entry = priv->cur_rx[q] % priv->num_rx_ring[q];
-       boguscnt = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
+       limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
        stats = &priv->stats[q];
 
-       boguscnt = min(boguscnt, *quota);
-       limit = boguscnt;
        desc = &priv->gbeth_rx_ring[entry];
-       while (desc->die_dt != DT_FEMPTY) {
+       for (i = 0; i < limit && rx_packets < *quota && desc->die_dt != DT_FEMPTY; i++) {
                /* Descriptor type must be checked before all other reads */
                dma_rmb();
                desc_status = desc->msc;
                pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS;
 
-               if (--boguscnt < 0)
-                       break;
-
                /* We use 0-byte descriptors to mark the DMA mapping errors */
                if (!pkt_len)
                        continue;
@@ -820,7 +816,7 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
                                skb_put(skb, pkt_len);
                                skb->protocol = eth_type_trans(skb, ndev);
                                napi_gro_receive(&priv->napi[q], skb);
-                               stats->rx_packets++;
+                               rx_packets++;
                                stats->rx_bytes += pkt_len;
                                break;
                        case DT_FSTART:
@@ -848,7 +844,7 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
                                        eth_type_trans(priv->rx_1st_skb, ndev);
                                napi_gro_receive(&priv->napi[q],
                                                 priv->rx_1st_skb);
-                               stats->rx_packets++;
+                               rx_packets++;
                                stats->rx_bytes += pkt_len;
                                break;
                        }
@@ -887,9 +883,9 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
                desc->die_dt = DT_FEMPTY;
        }
 
-       *quota -= limit - (++boguscnt);
-
-       return boguscnt <= 0;
+       stats->rx_packets += rx_packets;
+       *quota -= rx_packets;
+       return *quota == 0;
 }
 
 /* Packet receive function for Ethernet AVB */
index 721c1f8e892fc56ed1e9144619aa32ac676226b1..5ba606a596e779bc17081c55e5bf5c52555ada0b 100644 (file)
 #undef FRAME_FILTER_DEBUG
 /* #define FRAME_FILTER_DEBUG */
 
+struct stmmac_q_tx_stats {
+       u64_stats_t tx_bytes;
+       u64_stats_t tx_set_ic_bit;
+       u64_stats_t tx_tso_frames;
+       u64_stats_t tx_tso_nfrags;
+};
+
+struct stmmac_napi_tx_stats {
+       u64_stats_t tx_packets;
+       u64_stats_t tx_pkt_n;
+       u64_stats_t poll;
+       u64_stats_t tx_clean;
+       u64_stats_t tx_set_ic_bit;
+};
+
 struct stmmac_txq_stats {
-       u64 tx_bytes;
-       u64 tx_packets;
-       u64 tx_pkt_n;
-       u64 tx_normal_irq_n;
-       u64 napi_poll;
-       u64 tx_clean;
-       u64 tx_set_ic_bit;
-       u64 tx_tso_frames;
-       u64 tx_tso_nfrags;
-       struct u64_stats_sync syncp;
+       /* Updates protected by tx queue lock. */
+       struct u64_stats_sync q_syncp;
+       struct stmmac_q_tx_stats q;
+
+       /* Updates protected by NAPI poll logic. */
+       struct u64_stats_sync napi_syncp;
+       struct stmmac_napi_tx_stats napi;
 } ____cacheline_aligned_in_smp;
 
+struct stmmac_napi_rx_stats {
+       u64_stats_t rx_bytes;
+       u64_stats_t rx_packets;
+       u64_stats_t rx_pkt_n;
+       u64_stats_t poll;
+};
+
 struct stmmac_rxq_stats {
-       u64 rx_bytes;
-       u64 rx_packets;
-       u64 rx_pkt_n;
-       u64 rx_normal_irq_n;
-       u64 napi_poll;
-       struct u64_stats_sync syncp;
+       /* Updates protected by NAPI poll logic. */
+       struct u64_stats_sync napi_syncp;
+       struct stmmac_napi_rx_stats napi;
 } ____cacheline_aligned_in_smp;
 
+/* Updates on each CPU protected by not allowing nested irqs. */
+struct stmmac_pcpu_stats {
+       struct u64_stats_sync syncp;
+       u64_stats_t rx_normal_irq_n[MTL_MAX_TX_QUEUES];
+       u64_stats_t tx_normal_irq_n[MTL_MAX_RX_QUEUES];
+};
+
 /* Extra statistic and debug information exposed by ethtool */
 struct stmmac_extra_stats {
        /* Transmit errors */
@@ -205,6 +228,7 @@ struct stmmac_extra_stats {
        /* per queue statistics */
        struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES];
        struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES];
+       struct stmmac_pcpu_stats __percpu *pcpu_stats;
        unsigned long rx_dropped;
        unsigned long rx_errors;
        unsigned long tx_dropped;
@@ -216,6 +240,7 @@ struct stmmac_safety_stats {
        unsigned long mac_errors[32];
        unsigned long mtl_errors[32];
        unsigned long dma_errors[32];
+       unsigned long dma_dpp_errors[32];
 };
 
 /* Number of fields in Safety Stats */
index 137741b94122e5e99320eea5cad9909e6394dc7d..b21d99faa2d04c985427af61724dd073e3a2fe79 100644 (file)
@@ -441,8 +441,7 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
                                     struct stmmac_extra_stats *x, u32 chan,
                                     u32 dir)
 {
-       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
-       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
+       struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
        int ret = 0;
        u32 v;
 
@@ -455,9 +454,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
 
        if (v & EMAC_TX_INT) {
                ret |= handle_tx;
-               u64_stats_update_begin(&txq_stats->syncp);
-               txq_stats->tx_normal_irq_n++;
-               u64_stats_update_end(&txq_stats->syncp);
+               u64_stats_update_begin(&stats->syncp);
+               u64_stats_inc(&stats->tx_normal_irq_n[chan]);
+               u64_stats_update_end(&stats->syncp);
        }
 
        if (v & EMAC_TX_DMA_STOP_INT)
@@ -479,9 +478,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
 
        if (v & EMAC_RX_INT) {
                ret |= handle_rx;
-               u64_stats_update_begin(&rxq_stats->syncp);
-               rxq_stats->rx_normal_irq_n++;
-               u64_stats_update_end(&rxq_stats->syncp);
+               u64_stats_update_begin(&stats->syncp);
+               u64_stats_inc(&stats->rx_normal_irq_n[chan]);
+               u64_stats_update_end(&stats->syncp);
        }
 
        if (v & EMAC_RX_BUF_UA_INT)
index 9470d3fd2dede2bb436c05f6a92d87824c2db733..0d185e54eb7e24cfd4ef8de38e976aabd3ee9084 100644 (file)
@@ -171,8 +171,7 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
        const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
        u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan));
        u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
-       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
-       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
+       struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
        int ret = 0;
 
        if (dir == DMA_DIR_RX)
@@ -201,15 +200,15 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
        }
        /* TX/RX NORMAL interrupts */
        if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
-               u64_stats_update_begin(&rxq_stats->syncp);
-               rxq_stats->rx_normal_irq_n++;
-               u64_stats_update_end(&rxq_stats->syncp);
+               u64_stats_update_begin(&stats->syncp);
+               u64_stats_inc(&stats->rx_normal_irq_n[chan]);
+               u64_stats_update_end(&stats->syncp);
                ret |= handle_rx;
        }
        if (likely(intr_status & DMA_CHAN_STATUS_TI)) {
-               u64_stats_update_begin(&txq_stats->syncp);
-               txq_stats->tx_normal_irq_n++;
-               u64_stats_update_end(&txq_stats->syncp);
+               u64_stats_update_begin(&stats->syncp);
+               u64_stats_inc(&stats->tx_normal_irq_n[chan]);
+               u64_stats_update_end(&stats->syncp);
                ret |= handle_tx;
        }
 
index 7907d62d343759d661e00452198ef8e6cfef3601..85e18f9a22f92091bb98f1892d7bb1f5f08bcf2a 100644 (file)
@@ -162,8 +162,7 @@ static void show_rx_process_state(unsigned int status)
 int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
                        struct stmmac_extra_stats *x, u32 chan, u32 dir)
 {
-       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
-       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
+       struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
        int ret = 0;
        /* read the status register (CSR5) */
        u32 intr_status = readl(ioaddr + DMA_STATUS);
@@ -215,16 +214,16 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
                        u32 value = readl(ioaddr + DMA_INTR_ENA);
                        /* to schedule NAPI on real RIE event. */
                        if (likely(value & DMA_INTR_ENA_RIE)) {
-                               u64_stats_update_begin(&rxq_stats->syncp);
-                               rxq_stats->rx_normal_irq_n++;
-                               u64_stats_update_end(&rxq_stats->syncp);
+                               u64_stats_update_begin(&stats->syncp);
+                               u64_stats_inc(&stats->rx_normal_irq_n[chan]);
+                               u64_stats_update_end(&stats->syncp);
                                ret |= handle_rx;
                        }
                }
                if (likely(intr_status & DMA_STATUS_TI)) {
-                       u64_stats_update_begin(&txq_stats->syncp);
-                       txq_stats->tx_normal_irq_n++;
-                       u64_stats_update_end(&txq_stats->syncp);
+                       u64_stats_update_begin(&stats->syncp);
+                       u64_stats_inc(&stats->tx_normal_irq_n[chan]);
+                       u64_stats_update_end(&stats->syncp);
                        ret |= handle_tx;
                }
                if (unlikely(intr_status & DMA_STATUS_ERI))
index 207ff1799f2c712fe1e10033fa4d2b32dbd197c6..6a2c7d22df1eb81dd216e00e7525bc8a9092c048 100644 (file)
 #define XGMAC_RXCEIE                   BIT(4)
 #define XGMAC_TXCEIE                   BIT(0)
 #define XGMAC_MTL_ECC_INT_STATUS       0x000010cc
+#define XGMAC_MTL_DPP_CONTROL          0x000010e0
+#define XGMAC_DPP_DISABLE              BIT(0)
 #define XGMAC_MTL_TXQ_OPMODE(x)                (0x00001100 + (0x80 * (x)))
 #define XGMAC_TQS                      GENMASK(25, 16)
 #define XGMAC_TQS_SHIFT                        16
 #define XGMAC_DCEIE                    BIT(1)
 #define XGMAC_TCEIE                    BIT(0)
 #define XGMAC_DMA_ECC_INT_STATUS       0x0000306c
+#define XGMAC_DMA_DPP_INT_STATUS       0x00003074
 #define XGMAC_DMA_CH_CONTROL(x)                (0x00003100 + (0x80 * (x)))
 #define XGMAC_SPH                      BIT(24)
 #define XGMAC_PBLx8                    BIT(16)
index eb48211d9b0eb7013b436b0336c75f512fbf638a..1af2f89a0504ab4c7ad6042e52f5898ba064df6c 100644 (file)
@@ -830,6 +830,44 @@ static const struct dwxgmac3_error_desc dwxgmac3_dma_errors[32]= {
        { false, "UNKNOWN", "Unknown Error" }, /* 31 */
 };
 
+#define DPP_RX_ERR "Read Rx Descriptor Parity checker Error"
+#define DPP_TX_ERR "Read Tx Descriptor Parity checker Error"
+
+static const struct dwxgmac3_error_desc dwxgmac3_dma_dpp_errors[32] = {
+       { true, "TDPES0", DPP_TX_ERR },
+       { true, "TDPES1", DPP_TX_ERR },
+       { true, "TDPES2", DPP_TX_ERR },
+       { true, "TDPES3", DPP_TX_ERR },
+       { true, "TDPES4", DPP_TX_ERR },
+       { true, "TDPES5", DPP_TX_ERR },
+       { true, "TDPES6", DPP_TX_ERR },
+       { true, "TDPES7", DPP_TX_ERR },
+       { true, "TDPES8", DPP_TX_ERR },
+       { true, "TDPES9", DPP_TX_ERR },
+       { true, "TDPES10", DPP_TX_ERR },
+       { true, "TDPES11", DPP_TX_ERR },
+       { true, "TDPES12", DPP_TX_ERR },
+       { true, "TDPES13", DPP_TX_ERR },
+       { true, "TDPES14", DPP_TX_ERR },
+       { true, "TDPES15", DPP_TX_ERR },
+       { true, "RDPES0", DPP_RX_ERR },
+       { true, "RDPES1", DPP_RX_ERR },
+       { true, "RDPES2", DPP_RX_ERR },
+       { true, "RDPES3", DPP_RX_ERR },
+       { true, "RDPES4", DPP_RX_ERR },
+       { true, "RDPES5", DPP_RX_ERR },
+       { true, "RDPES6", DPP_RX_ERR },
+       { true, "RDPES7", DPP_RX_ERR },
+       { true, "RDPES8", DPP_RX_ERR },
+       { true, "RDPES9", DPP_RX_ERR },
+       { true, "RDPES10", DPP_RX_ERR },
+       { true, "RDPES11", DPP_RX_ERR },
+       { true, "RDPES12", DPP_RX_ERR },
+       { true, "RDPES13", DPP_RX_ERR },
+       { true, "RDPES14", DPP_RX_ERR },
+       { true, "RDPES15", DPP_RX_ERR },
+};
+
 static void dwxgmac3_handle_dma_err(struct net_device *ndev,
                                    void __iomem *ioaddr, bool correctable,
                                    struct stmmac_safety_stats *stats)
@@ -841,6 +879,13 @@ static void dwxgmac3_handle_dma_err(struct net_device *ndev,
 
        dwxgmac3_log_error(ndev, value, correctable, "DMA",
                           dwxgmac3_dma_errors, STAT_OFF(dma_errors), stats);
+
+       value = readl(ioaddr + XGMAC_DMA_DPP_INT_STATUS);
+       writel(value, ioaddr + XGMAC_DMA_DPP_INT_STATUS);
+
+       dwxgmac3_log_error(ndev, value, false, "DMA_DPP",
+                          dwxgmac3_dma_dpp_errors,
+                          STAT_OFF(dma_dpp_errors), stats);
 }
 
 static int
@@ -881,6 +926,12 @@ dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp,
        value |= XGMAC_TMOUTEN; /* FSM Timeout Feature */
        writel(value, ioaddr + XGMAC_MAC_FSM_CONTROL);
 
+       /* 5. Enable Data Path Parity Protection */
+       value = readl(ioaddr + XGMAC_MTL_DPP_CONTROL);
+       /* already enabled by default, explicit enable it again */
+       value &= ~XGMAC_DPP_DISABLE;
+       writel(value, ioaddr + XGMAC_MTL_DPP_CONTROL);
+
        return 0;
 }
 
@@ -914,7 +965,11 @@ static int dwxgmac3_safety_feat_irq_status(struct net_device *ndev,
                ret |= !corr;
        }
 
-       err = dma & (XGMAC_DEUIS | XGMAC_DECIS);
+       /* DMA_DPP_Interrupt_Status is indicated by MCSIS bit in
+        * DMA_Safety_Interrupt_Status, so we handle DMA Data Path
+        * Parity Errors here
+        */
+       err = dma & (XGMAC_DEUIS | XGMAC_DECIS | XGMAC_MCSIS);
        corr = dma & XGMAC_DECIS;
        if (err) {
                dwxgmac3_handle_dma_err(ndev, ioaddr, corr, stats);
@@ -930,6 +985,7 @@ static const struct dwxgmac3_error {
        { dwxgmac3_mac_errors },
        { dwxgmac3_mtl_errors },
        { dwxgmac3_dma_errors },
+       { dwxgmac3_dma_dpp_errors },
 };
 
 static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats,
index 3cde695fec91bd7592e23e725517f0cccee08a42..dd2ab6185c40e813ee4401857875d3e8478303e7 100644 (file)
@@ -337,8 +337,7 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
                                  struct stmmac_extra_stats *x, u32 chan,
                                  u32 dir)
 {
-       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
-       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
+       struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
        u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));
        u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
        int ret = 0;
@@ -367,15 +366,15 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
        /* TX/RX NORMAL interrupts */
        if (likely(intr_status & XGMAC_NIS)) {
                if (likely(intr_status & XGMAC_RI)) {
-                       u64_stats_update_begin(&rxq_stats->syncp);
-                       rxq_stats->rx_normal_irq_n++;
-                       u64_stats_update_end(&rxq_stats->syncp);
+                       u64_stats_update_begin(&stats->syncp);
+                       u64_stats_inc(&stats->rx_normal_irq_n[chan]);
+                       u64_stats_update_end(&stats->syncp);
                        ret |= handle_rx;
                }
                if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {
-                       u64_stats_update_begin(&txq_stats->syncp);
-                       txq_stats->tx_normal_irq_n++;
-                       u64_stats_update_end(&txq_stats->syncp);
+                       u64_stats_update_begin(&stats->syncp);
+                       u64_stats_inc(&stats->tx_normal_irq_n[chan]);
+                       u64_stats_update_end(&stats->syncp);
                        ret |= handle_tx;
                }
        }
index 42d27b97dd1d036e1410131060b65220b0ab2180..ec44becf0e2d289c4f6aeab983c54e93d70faf75 100644 (file)
@@ -549,44 +549,79 @@ stmmac_set_pauseparam(struct net_device *netdev,
        }
 }
 
+static u64 stmmac_get_rx_normal_irq_n(struct stmmac_priv *priv, int q)
+{
+       u64 total;
+       int cpu;
+
+       total = 0;
+       for_each_possible_cpu(cpu) {
+               struct stmmac_pcpu_stats *pcpu;
+               unsigned int start;
+               u64 irq_n;
+
+               pcpu = per_cpu_ptr(priv->xstats.pcpu_stats, cpu);
+               do {
+                       start = u64_stats_fetch_begin(&pcpu->syncp);
+                       irq_n = u64_stats_read(&pcpu->rx_normal_irq_n[q]);
+               } while (u64_stats_fetch_retry(&pcpu->syncp, start));
+               total += irq_n;
+       }
+       return total;
+}
+
+static u64 stmmac_get_tx_normal_irq_n(struct stmmac_priv *priv, int q)
+{
+       u64 total;
+       int cpu;
+
+       total = 0;
+       for_each_possible_cpu(cpu) {
+               struct stmmac_pcpu_stats *pcpu;
+               unsigned int start;
+               u64 irq_n;
+
+               pcpu = per_cpu_ptr(priv->xstats.pcpu_stats, cpu);
+               do {
+                       start = u64_stats_fetch_begin(&pcpu->syncp);
+                       irq_n = u64_stats_read(&pcpu->tx_normal_irq_n[q]);
+               } while (u64_stats_fetch_retry(&pcpu->syncp, start));
+               total += irq_n;
+       }
+       return total;
+}
+
 static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data)
 {
        u32 tx_cnt = priv->plat->tx_queues_to_use;
        u32 rx_cnt = priv->plat->rx_queues_to_use;
        unsigned int start;
-       int q, stat;
-       char *p;
+       int q;
 
        for (q = 0; q < tx_cnt; q++) {
                struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[q];
-               struct stmmac_txq_stats snapshot;
+               u64 pkt_n;
 
                do {
-                       start = u64_stats_fetch_begin(&txq_stats->syncp);
-                       snapshot = *txq_stats;
-               } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+                       start = u64_stats_fetch_begin(&txq_stats->napi_syncp);
+                       pkt_n = u64_stats_read(&txq_stats->napi.tx_pkt_n);
+               } while (u64_stats_fetch_retry(&txq_stats->napi_syncp, start));
 
-               p = (char *)&snapshot + offsetof(struct stmmac_txq_stats, tx_pkt_n);
-               for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) {
-                       *data++ = (*(u64 *)p);
-                       p += sizeof(u64);
-               }
+               *data++ = pkt_n;
+               *data++ = stmmac_get_tx_normal_irq_n(priv, q);
        }
 
        for (q = 0; q < rx_cnt; q++) {
                struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[q];
-               struct stmmac_rxq_stats snapshot;
+               u64 pkt_n;
 
                do {
-                       start = u64_stats_fetch_begin(&rxq_stats->syncp);
-                       snapshot = *rxq_stats;
-               } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+                       start = u64_stats_fetch_begin(&rxq_stats->napi_syncp);
+                       pkt_n = u64_stats_read(&rxq_stats->napi.rx_pkt_n);
+               } while (u64_stats_fetch_retry(&rxq_stats->napi_syncp, start));
 
-               p = (char *)&snapshot + offsetof(struct stmmac_rxq_stats, rx_pkt_n);
-               for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) {
-                       *data++ = (*(u64 *)p);
-                       p += sizeof(u64);
-               }
+               *data++ = pkt_n;
+               *data++ = stmmac_get_rx_normal_irq_n(priv, q);
        }
 }
 
@@ -645,39 +680,49 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
        pos = j;
        for (i = 0; i < rx_queues_count; i++) {
                struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[i];
-               struct stmmac_rxq_stats snapshot;
+               struct stmmac_napi_rx_stats snapshot;
+               u64 n_irq;
 
                j = pos;
                do {
-                       start = u64_stats_fetch_begin(&rxq_stats->syncp);
-                       snapshot = *rxq_stats;
-               } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
-
-               data[j++] += snapshot.rx_pkt_n;
-               data[j++] += snapshot.rx_normal_irq_n;
-               normal_irq_n += snapshot.rx_normal_irq_n;
-               napi_poll += snapshot.napi_poll;
+                       start = u64_stats_fetch_begin(&rxq_stats->napi_syncp);
+                       snapshot = rxq_stats->napi;
+               } while (u64_stats_fetch_retry(&rxq_stats->napi_syncp, start));
+
+               data[j++] += u64_stats_read(&snapshot.rx_pkt_n);
+               n_irq = stmmac_get_rx_normal_irq_n(priv, i);
+               data[j++] += n_irq;
+               normal_irq_n += n_irq;
+               napi_poll += u64_stats_read(&snapshot.poll);
        }
 
        pos = j;
        for (i = 0; i < tx_queues_count; i++) {
                struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[i];
-               struct stmmac_txq_stats snapshot;
+               struct stmmac_napi_tx_stats napi_snapshot;
+               struct stmmac_q_tx_stats q_snapshot;
+               u64 n_irq;
 
                j = pos;
                do {
-                       start = u64_stats_fetch_begin(&txq_stats->syncp);
-                       snapshot = *txq_stats;
-               } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
-
-               data[j++] += snapshot.tx_pkt_n;
-               data[j++] += snapshot.tx_normal_irq_n;
-               normal_irq_n += snapshot.tx_normal_irq_n;
-               data[j++] += snapshot.tx_clean;
-               data[j++] += snapshot.tx_set_ic_bit;
-               data[j++] += snapshot.tx_tso_frames;
-               data[j++] += snapshot.tx_tso_nfrags;
-               napi_poll += snapshot.napi_poll;
+                       start = u64_stats_fetch_begin(&txq_stats->q_syncp);
+                       q_snapshot = txq_stats->q;
+               } while (u64_stats_fetch_retry(&txq_stats->q_syncp, start));
+               do {
+                       start = u64_stats_fetch_begin(&txq_stats->napi_syncp);
+                       napi_snapshot = txq_stats->napi;
+               } while (u64_stats_fetch_retry(&txq_stats->napi_syncp, start));
+
+               data[j++] += u64_stats_read(&napi_snapshot.tx_pkt_n);
+               n_irq = stmmac_get_tx_normal_irq_n(priv, i);
+               data[j++] += n_irq;
+               normal_irq_n += n_irq;
+               data[j++] += u64_stats_read(&napi_snapshot.tx_clean);
+               data[j++] += u64_stats_read(&q_snapshot.tx_set_ic_bit) +
+                       u64_stats_read(&napi_snapshot.tx_set_ic_bit);
+               data[j++] += u64_stats_read(&q_snapshot.tx_tso_frames);
+               data[j++] += u64_stats_read(&q_snapshot.tx_tso_nfrags);
+               napi_poll += u64_stats_read(&napi_snapshot.poll);
        }
        normal_irq_n += priv->xstats.rx_early_irq;
        data[j++] = normal_irq_n;
index 25519952f754ca0e03b39baa0bb6ab06aebd4209..75d02970450321be0e8f8e3bc2b0e0330f17e4af 100644 (file)
@@ -2482,7 +2482,6 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
        struct xdp_desc xdp_desc;
        bool work_done = true;
        u32 tx_set_ic_bit = 0;
-       unsigned long flags;
 
        /* Avoids TX time-out as we are sharing with slow path */
        txq_trans_cond_update(nq);
@@ -2566,9 +2565,9 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
                tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
                entry = tx_q->cur_tx;
        }
-       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
-       txq_stats->tx_set_ic_bit += tx_set_ic_bit;
-       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
+       u64_stats_update_begin(&txq_stats->napi_syncp);
+       u64_stats_add(&txq_stats->napi.tx_set_ic_bit, tx_set_ic_bit);
+       u64_stats_update_end(&txq_stats->napi_syncp);
 
        if (tx_desc) {
                stmmac_flush_tx_descriptors(priv, queue);
@@ -2616,7 +2615,6 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue,
        unsigned int bytes_compl = 0, pkts_compl = 0;
        unsigned int entry, xmits = 0, count = 0;
        u32 tx_packets = 0, tx_errors = 0;
-       unsigned long flags;
 
        __netif_tx_lock_bh(netdev_get_tx_queue(priv->dev, queue));
 
@@ -2782,11 +2780,11 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue,
        if (tx_q->dirty_tx != tx_q->cur_tx)
                *pending_packets = true;
 
-       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
-       txq_stats->tx_packets += tx_packets;
-       txq_stats->tx_pkt_n += tx_packets;
-       txq_stats->tx_clean++;
-       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
+       u64_stats_update_begin(&txq_stats->napi_syncp);
+       u64_stats_add(&txq_stats->napi.tx_packets, tx_packets);
+       u64_stats_add(&txq_stats->napi.tx_pkt_n, tx_packets);
+       u64_stats_inc(&txq_stats->napi.tx_clean);
+       u64_stats_update_end(&txq_stats->napi_syncp);
 
        priv->xstats.tx_errors += tx_errors;
 
@@ -4213,7 +4211,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
        struct stmmac_tx_queue *tx_q;
        bool has_vlan, set_ic;
        u8 proto_hdr_len, hdr;
-       unsigned long flags;
        u32 pay_len, mss;
        dma_addr_t des;
        int i;
@@ -4378,13 +4375,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
                netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue));
        }
 
-       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
-       txq_stats->tx_bytes += skb->len;
-       txq_stats->tx_tso_frames++;
-       txq_stats->tx_tso_nfrags += nfrags;
+       u64_stats_update_begin(&txq_stats->q_syncp);
+       u64_stats_add(&txq_stats->q.tx_bytes, skb->len);
+       u64_stats_inc(&txq_stats->q.tx_tso_frames);
+       u64_stats_add(&txq_stats->q.tx_tso_nfrags, nfrags);
        if (set_ic)
-               txq_stats->tx_set_ic_bit++;
-       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
+               u64_stats_inc(&txq_stats->q.tx_set_ic_bit);
+       u64_stats_update_end(&txq_stats->q_syncp);
 
        if (priv->sarc_type)
                stmmac_set_desc_sarc(priv, first, priv->sarc_type);
@@ -4483,7 +4480,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        struct stmmac_tx_queue *tx_q;
        bool has_vlan, set_ic;
        int entry, first_tx;
-       unsigned long flags;
        dma_addr_t des;
 
        tx_q = &priv->dma_conf.tx_queue[queue];
@@ -4653,11 +4649,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue));
        }
 
-       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
-       txq_stats->tx_bytes += skb->len;
+       u64_stats_update_begin(&txq_stats->q_syncp);
+       u64_stats_add(&txq_stats->q.tx_bytes, skb->len);
        if (set_ic)
-               txq_stats->tx_set_ic_bit++;
-       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
+               u64_stats_inc(&txq_stats->q.tx_set_ic_bit);
+       u64_stats_update_end(&txq_stats->q_syncp);
 
        if (priv->sarc_type)
                stmmac_set_desc_sarc(priv, first, priv->sarc_type);
@@ -4921,12 +4917,11 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
                set_ic = false;
 
        if (set_ic) {
-               unsigned long flags;
                tx_q->tx_count_frames = 0;
                stmmac_set_tx_ic(priv, tx_desc);
-               flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
-               txq_stats->tx_set_ic_bit++;
-               u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
+               u64_stats_update_begin(&txq_stats->q_syncp);
+               u64_stats_inc(&txq_stats->q.tx_set_ic_bit);
+               u64_stats_update_end(&txq_stats->q_syncp);
        }
 
        stmmac_enable_dma_transmission(priv, priv->ioaddr);
@@ -5076,7 +5071,6 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue,
        unsigned int len = xdp->data_end - xdp->data;
        enum pkt_hash_types hash_type;
        int coe = priv->hw->rx_csum;
-       unsigned long flags;
        struct sk_buff *skb;
        u32 hash;
 
@@ -5106,10 +5100,10 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue,
        skb_record_rx_queue(skb, queue);
        napi_gro_receive(&ch->rxtx_napi, skb);
 
-       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
-       rxq_stats->rx_pkt_n++;
-       rxq_stats->rx_bytes += len;
-       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
+       u64_stats_update_begin(&rxq_stats->napi_syncp);
+       u64_stats_inc(&rxq_stats->napi.rx_pkt_n);
+       u64_stats_add(&rxq_stats->napi.rx_bytes, len);
+       u64_stats_update_end(&rxq_stats->napi_syncp);
 }
 
 static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
@@ -5191,7 +5185,6 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
        unsigned int desc_size;
        struct bpf_prog *prog;
        bool failure = false;
-       unsigned long flags;
        int xdp_status = 0;
        int status = 0;
 
@@ -5346,9 +5339,9 @@ read_again:
 
        stmmac_finalize_xdp_rx(priv, xdp_status);
 
-       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
-       rxq_stats->rx_pkt_n += count;
-       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
+       u64_stats_update_begin(&rxq_stats->napi_syncp);
+       u64_stats_add(&rxq_stats->napi.rx_pkt_n, count);
+       u64_stats_update_end(&rxq_stats->napi_syncp);
 
        priv->xstats.rx_dropped += rx_dropped;
        priv->xstats.rx_errors += rx_errors;
@@ -5386,7 +5379,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
        unsigned int desc_size;
        struct sk_buff *skb = NULL;
        struct stmmac_xdp_buff ctx;
-       unsigned long flags;
        int xdp_status = 0;
        int buf_sz;
 
@@ -5646,11 +5638,11 @@ drain_data:
 
        stmmac_rx_refill(priv, queue);
 
-       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
-       rxq_stats->rx_packets += rx_packets;
-       rxq_stats->rx_bytes += rx_bytes;
-       rxq_stats->rx_pkt_n += count;
-       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
+       u64_stats_update_begin(&rxq_stats->napi_syncp);
+       u64_stats_add(&rxq_stats->napi.rx_packets, rx_packets);
+       u64_stats_add(&rxq_stats->napi.rx_bytes, rx_bytes);
+       u64_stats_add(&rxq_stats->napi.rx_pkt_n, count);
+       u64_stats_update_end(&rxq_stats->napi_syncp);
 
        priv->xstats.rx_dropped += rx_dropped;
        priv->xstats.rx_errors += rx_errors;
@@ -5665,13 +5657,12 @@ static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget)
        struct stmmac_priv *priv = ch->priv_data;
        struct stmmac_rxq_stats *rxq_stats;
        u32 chan = ch->index;
-       unsigned long flags;
        int work_done;
 
        rxq_stats = &priv->xstats.rxq_stats[chan];
-       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
-       rxq_stats->napi_poll++;
-       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
+       u64_stats_update_begin(&rxq_stats->napi_syncp);
+       u64_stats_inc(&rxq_stats->napi.poll);
+       u64_stats_update_end(&rxq_stats->napi_syncp);
 
        work_done = stmmac_rx(priv, budget, chan);
        if (work_done < budget && napi_complete_done(napi, work_done)) {
@@ -5693,13 +5684,12 @@ static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget)
        struct stmmac_txq_stats *txq_stats;
        bool pending_packets = false;
        u32 chan = ch->index;
-       unsigned long flags;
        int work_done;
 
        txq_stats = &priv->xstats.txq_stats[chan];
-       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
-       txq_stats->napi_poll++;
-       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
+       u64_stats_update_begin(&txq_stats->napi_syncp);
+       u64_stats_inc(&txq_stats->napi.poll);
+       u64_stats_update_end(&txq_stats->napi_syncp);
 
        work_done = stmmac_tx_clean(priv, budget, chan, &pending_packets);
        work_done = min(work_done, budget);
@@ -5729,17 +5719,16 @@ static int stmmac_napi_poll_rxtx(struct napi_struct *napi, int budget)
        struct stmmac_rxq_stats *rxq_stats;
        struct stmmac_txq_stats *txq_stats;
        u32 chan = ch->index;
-       unsigned long flags;
 
        rxq_stats = &priv->xstats.rxq_stats[chan];
-       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
-       rxq_stats->napi_poll++;
-       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
+       u64_stats_update_begin(&rxq_stats->napi_syncp);
+       u64_stats_inc(&rxq_stats->napi.poll);
+       u64_stats_update_end(&rxq_stats->napi_syncp);
 
        txq_stats = &priv->xstats.txq_stats[chan];
-       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
-       txq_stats->napi_poll++;
-       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
+       u64_stats_update_begin(&txq_stats->napi_syncp);
+       u64_stats_inc(&txq_stats->napi.poll);
+       u64_stats_update_end(&txq_stats->napi_syncp);
 
        tx_done = stmmac_tx_clean(priv, budget, chan, &tx_pending_packets);
        tx_done = min(tx_done, budget);
@@ -7065,10 +7054,13 @@ static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64
                u64 tx_bytes;
 
                do {
-                       start = u64_stats_fetch_begin(&txq_stats->syncp);
-                       tx_packets = txq_stats->tx_packets;
-                       tx_bytes   = txq_stats->tx_bytes;
-               } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+                       start = u64_stats_fetch_begin(&txq_stats->q_syncp);
+                       tx_bytes   = u64_stats_read(&txq_stats->q.tx_bytes);
+               } while (u64_stats_fetch_retry(&txq_stats->q_syncp, start));
+               do {
+                       start = u64_stats_fetch_begin(&txq_stats->napi_syncp);
+                       tx_packets = u64_stats_read(&txq_stats->napi.tx_packets);
+               } while (u64_stats_fetch_retry(&txq_stats->napi_syncp, start));
 
                stats->tx_packets += tx_packets;
                stats->tx_bytes += tx_bytes;
@@ -7080,10 +7072,10 @@ static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64
                u64 rx_bytes;
 
                do {
-                       start = u64_stats_fetch_begin(&rxq_stats->syncp);
-                       rx_packets = rxq_stats->rx_packets;
-                       rx_bytes   = rxq_stats->rx_bytes;
-               } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+                       start = u64_stats_fetch_begin(&rxq_stats->napi_syncp);
+                       rx_packets = u64_stats_read(&rxq_stats->napi.rx_packets);
+                       rx_bytes   = u64_stats_read(&rxq_stats->napi.rx_bytes);
+               } while (u64_stats_fetch_retry(&rxq_stats->napi_syncp, start));
 
                stats->rx_packets += rx_packets;
                stats->rx_bytes += rx_bytes;
@@ -7477,9 +7469,16 @@ int stmmac_dvr_probe(struct device *device,
        priv->dev = ndev;
 
        for (i = 0; i < MTL_MAX_RX_QUEUES; i++)
-               u64_stats_init(&priv->xstats.rxq_stats[i].syncp);
-       for (i = 0; i < MTL_MAX_TX_QUEUES; i++)
-               u64_stats_init(&priv->xstats.txq_stats[i].syncp);
+               u64_stats_init(&priv->xstats.rxq_stats[i].napi_syncp);
+       for (i = 0; i < MTL_MAX_TX_QUEUES; i++) {
+               u64_stats_init(&priv->xstats.txq_stats[i].q_syncp);
+               u64_stats_init(&priv->xstats.txq_stats[i].napi_syncp);
+       }
+
+       priv->xstats.pcpu_stats =
+               devm_netdev_alloc_pcpu_stats(device, struct stmmac_pcpu_stats);
+       if (!priv->xstats.pcpu_stats)
+               return -ENOMEM;
 
        stmmac_set_ethtool_ops(ndev);
        priv->pause = pause;
index be01450c20dc0199ebc5d1d731eca04a47781539..1530d13984d42606f6e4b4d1d28ca3f8c6461ac0 100644 (file)
@@ -189,6 +189,7 @@ config TI_ICSSG_PRUETH
        select TI_K3_CPPI_DESC_POOL
        depends on PRU_REMOTEPROC
        depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
+       depends on PTP_1588_CLOCK_OPTIONAL
        help
          Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem.
          This subsystem is available starting with the AM65 platform.
index ea85c6dd5484617a038e565312e8ad0ccdce6c75..c0a5abd8d9a8e6e0d113c36a9557a1de1c360993 100644 (file)
@@ -631,6 +631,8 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
                }
        }
 
+       phy->mac_managed_pm = true;
+
        slave->phy = phy;
 
        phy_attached_info(slave->phy);
index 498c50c6d1a701b86596b9148dbdc4523176cee7..087dcb67505a2da5995963d5d67d36dadb580a47 100644 (file)
@@ -773,6 +773,9 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
                        slave->slave_num);
                return;
        }
+
+       phy->mac_managed_pm = true;
+
        slave->phy = phy;
 
        phy_attached_info(slave->phy);
index bcccf43d368b7e2a9efc3a6e855a5b2299e9cdc4..dbbea914604057ca97823c5c6e164be50303df08 100644 (file)
@@ -638,6 +638,16 @@ static void cpts_calc_mult_shift(struct cpts *cpts)
                 freq, cpts->cc.mult, cpts->cc.shift, (ns - NSEC_PER_SEC));
 }
 
+static void cpts_clk_unregister(void *clk)
+{
+       clk_hw_unregister_mux(clk);
+}
+
+static void cpts_clk_del_provider(void *np)
+{
+       of_clk_del_provider(np);
+}
+
 static int cpts_of_mux_clk_setup(struct cpts *cpts, struct device_node *node)
 {
        struct device_node *refclk_np;
@@ -687,9 +697,7 @@ static int cpts_of_mux_clk_setup(struct cpts *cpts, struct device_node *node)
                goto mux_fail;
        }
 
-       ret = devm_add_action_or_reset(cpts->dev,
-                                      (void(*)(void *))clk_hw_unregister_mux,
-                                      clk_hw);
+       ret = devm_add_action_or_reset(cpts->dev, cpts_clk_unregister, clk_hw);
        if (ret) {
                dev_err(cpts->dev, "add clkmux unreg action %d", ret);
                goto mux_fail;
@@ -699,8 +707,7 @@ static int cpts_of_mux_clk_setup(struct cpts *cpts, struct device_node *node)
        if (ret)
                goto mux_fail;
 
-       ret = devm_add_action_or_reset(cpts->dev,
-                                      (void(*)(void *))of_clk_del_provider,
+       ret = devm_add_action_or_reset(cpts->dev, cpts_clk_del_provider,
                                       refclk_np);
        if (ret) {
                dev_err(cpts->dev, "add clkmux provider unreg action %d", ret);
index 2b6a607ac0b78848d8694af42df349aaa24f16d8..a273362c9e703ce8f807ae86e4705565ab51c605 100644 (file)
@@ -153,6 +153,7 @@ static const struct pci_device_id skfddi_pci_tbl[] = {
        { }                     /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, skfddi_pci_tbl);
+MODULE_DESCRIPTION("SysKonnect FDDI PCI driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
 
index 273bd8a20122cdbec238326febb0227ca7889c8d..11831a1c97623985401317e690b66f6985abb750 100644 (file)
 #define LINKCHANGE_INT (2 * HZ)
 #define VF_TAKEOVER_INT (HZ / 10)
 
+/* Macros to define the context of vf registration */
+#define VF_REG_IN_PROBE                1
+#define VF_REG_IN_NOTIFIER     2
+
 static unsigned int ring_size __ro_after_init = 128;
 module_param(ring_size, uint, 0444);
 MODULE_PARM_DESC(ring_size, "Ring buffer size (# of 4K pages)");
@@ -2185,7 +2189,7 @@ static rx_handler_result_t netvsc_vf_handle_frame(struct sk_buff **pskb)
 }
 
 static int netvsc_vf_join(struct net_device *vf_netdev,
-                         struct net_device *ndev)
+                         struct net_device *ndev, int context)
 {
        struct net_device_context *ndev_ctx = netdev_priv(ndev);
        int ret;
@@ -2208,7 +2212,11 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
                goto upper_link_failed;
        }
 
-       schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
+       /* If this registration is called from probe context vf_takeover
+        * is taken care of later in probe itself.
+        */
+       if (context == VF_REG_IN_NOTIFIER)
+               schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
 
        call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
 
@@ -2346,7 +2354,7 @@ static int netvsc_prepare_bonding(struct net_device *vf_netdev)
        return NOTIFY_DONE;
 }
 
-static int netvsc_register_vf(struct net_device *vf_netdev)
+static int netvsc_register_vf(struct net_device *vf_netdev, int context)
 {
        struct net_device_context *net_device_ctx;
        struct netvsc_device *netvsc_dev;
@@ -2386,7 +2394,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
 
        netdev_info(ndev, "VF registering: %s\n", vf_netdev->name);
 
-       if (netvsc_vf_join(vf_netdev, ndev) != 0)
+       if (netvsc_vf_join(vf_netdev, ndev, context) != 0)
                return NOTIFY_DONE;
 
        dev_hold(vf_netdev);
@@ -2484,10 +2492,31 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
        return NOTIFY_OK;
 }
 
+static int check_dev_is_matching_vf(struct net_device *event_ndev)
+{
+       /* Skip NetVSC interfaces */
+       if (event_ndev->netdev_ops == &device_ops)
+               return -ENODEV;
+
+       /* Avoid non-Ethernet type devices */
+       if (event_ndev->type != ARPHRD_ETHER)
+               return -ENODEV;
+
+       /* Avoid Vlan dev with same MAC registering as VF */
+       if (is_vlan_dev(event_ndev))
+               return -ENODEV;
+
+       /* Avoid Bonding master dev with same MAC registering as VF */
+       if (netif_is_bond_master(event_ndev))
+               return -ENODEV;
+
+       return 0;
+}
+
 static int netvsc_probe(struct hv_device *dev,
                        const struct hv_vmbus_device_id *dev_id)
 {
-       struct net_device *net = NULL;
+       struct net_device *net = NULL, *vf_netdev;
        struct net_device_context *net_device_ctx;
        struct netvsc_device_info *device_info = NULL;
        struct netvsc_device *nvdev;
@@ -2599,6 +2628,30 @@ static int netvsc_probe(struct hv_device *dev,
        }
 
        list_add(&net_device_ctx->list, &netvsc_dev_list);
+
+       /* When the hv_netvsc driver is unloaded and reloaded, the
+        * NET_DEVICE_REGISTER for the vf device is replayed before probe
+        * is complete. This is because register_netdevice_notifier() gets
+        * registered before vmbus_driver_register() so that callback func
+        * is set before probe and we don't miss events like NETDEV_POST_INIT
+        * So, in this section we try to register the matching vf device that
+        * is present as a netdevice, knowing that its register call is not
+        * processed in the netvsc_netdev_notifier(as probing is progress and
+        * get_netvsc_byslot fails).
+        */
+       for_each_netdev(dev_net(net), vf_netdev) {
+               ret = check_dev_is_matching_vf(vf_netdev);
+               if (ret != 0)
+                       continue;
+
+               if (net != get_netvsc_byslot(vf_netdev))
+                       continue;
+
+               netvsc_prepare_bonding(vf_netdev);
+               netvsc_register_vf(vf_netdev, VF_REG_IN_PROBE);
+               __netvsc_vf_setup(net, vf_netdev);
+               break;
+       }
        rtnl_unlock();
 
        netvsc_devinfo_put(device_info);
@@ -2754,28 +2807,17 @@ static int netvsc_netdev_event(struct notifier_block *this,
                               unsigned long event, void *ptr)
 {
        struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+       int ret = 0;
 
-       /* Skip our own events */
-       if (event_dev->netdev_ops == &device_ops)
-               return NOTIFY_DONE;
-
-       /* Avoid non-Ethernet type devices */
-       if (event_dev->type != ARPHRD_ETHER)
-               return NOTIFY_DONE;
-
-       /* Avoid Vlan dev with same MAC registering as VF */
-       if (is_vlan_dev(event_dev))
-               return NOTIFY_DONE;
-
-       /* Avoid Bonding master dev with same MAC registering as VF */
-       if (netif_is_bond_master(event_dev))
+       ret = check_dev_is_matching_vf(event_dev);
+       if (ret != 0)
                return NOTIFY_DONE;
 
        switch (event) {
        case NETDEV_POST_INIT:
                return netvsc_prepare_bonding(event_dev);
        case NETDEV_REGISTER:
-               return netvsc_register_vf(event_dev);
+               return netvsc_register_vf(event_dev, VF_REG_IN_NOTIFIER);
        case NETDEV_UNREGISTER:
                return netvsc_unregister_vf(event_dev);
        case NETDEV_UP:
index 35e55f198e05cea45ddb747dff34963eabfac92e..2930141d7dd2d30201e4bd1d4492cbd681fb7c0a 100644 (file)
@@ -259,4 +259,5 @@ static __exit void fake_remove_module(void)
 
 module_init(fakelb_init_module);
 module_exit(fake_remove_module);
+MODULE_DESCRIPTION("IEEE 802.15.4 loopback driver");
 MODULE_LICENSE("GPL");
index 60944a4beadae611b2c2dd012683cb30052d0f6b..1afc4c47be73f906f58721aa227dd35fd30eff73 100644 (file)
@@ -237,4 +237,5 @@ static void __exit ipvtap_exit(void)
 module_exit(ipvtap_exit);
 MODULE_ALIAS_RTNL_LINK("ipvtap");
 MODULE_AUTHOR("Sainath Grandhi <sainath.grandhi@intel.com>");
+MODULE_DESCRIPTION("IP-VLAN based tap driver");
 MODULE_LICENSE("GPL");
index b4d3b9cde8bd685202f135cf9c845d1be76ef428..92a7a36b93ac0cc1b02a551b974fb390254ac484 100644 (file)
@@ -835,14 +835,14 @@ static void nsim_dev_trap_report_work(struct work_struct *work)
                                      trap_report_dw.work);
        nsim_dev = nsim_trap_data->nsim_dev;
 
-       /* For each running port and enabled packet trap, generate a UDP
-        * packet with a random 5-tuple and report it.
-        */
        if (!devl_trylock(priv_to_devlink(nsim_dev))) {
-               schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 0);
+               schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 1);
                return;
        }
 
+       /* For each running port and enabled packet trap, generate a UDP
+        * packet with a random 5-tuple and report it.
+        */
        list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) {
                if (!netif_running(nsim_dev_port->ns->netdev))
                        continue;
index 69b829e6ab35b84a07f0063f3a6f7b48ea1a6de1..7fd3377dbd7960adb2af9f19999b1a940b55fc33 100644 (file)
@@ -131,4 +131,5 @@ int __devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
 EXPORT_SYMBOL(__devm_of_mdiobus_register);
 #endif /* CONFIG_OF_MDIO */
 
+MODULE_DESCRIPTION("Network MDIO bus devres helpers");
 MODULE_LICENSE("GPL");
index 40ce8abe699954d106b216e8351925ec1cd9d3a1..cc7d1113ece0ee7d6cfa0e1830bbbdc664c28514 100644 (file)
@@ -1437,4 +1437,5 @@ static int __init plip_init (void)
 
 module_init(plip_init);
 module_exit(plip_cleanup_module);
+MODULE_DESCRIPTION("PLIP (parallel port) network module");
 MODULE_LICENSE("GPL");
index db0dc36d12e33ed7a481319c2d3a219ff88f3782..55954594e157e2eb6a4331e6da3b2d2ff547a4a3 100644 (file)
@@ -1166,5 +1166,6 @@ static void __exit bsdcomp_cleanup(void)
 
 module_init(bsdcomp_init);
 module_exit(bsdcomp_cleanup);
+MODULE_DESCRIPTION("PPP BSD-Compress compression module");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_ALIAS("ppp-compress-" __stringify(CI_BSD_COMPRESS));
index 840da924708b393b16a82ab4e07746538214c0f9..c33c3db3cc0896d9b033aa2b188fbf46be8afd68 100644 (file)
@@ -87,6 +87,7 @@ struct asyncppp {
 static int flag_time = HZ;
 module_param(flag_time, int, 0);
 MODULE_PARM_DESC(flag_time, "ppp_async: interval between flagged packets (in clock ticks)");
+MODULE_DESCRIPTION("PPP async serial channel module");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_LDISC(N_PPP);
 
@@ -460,6 +461,10 @@ ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
        case PPPIOCSMRU:
                if (get_user(val, p))
                        break;
+               if (val > U16_MAX) {
+                       err = -EINVAL;
+                       break;
+               }
                if (val < PPP_MRU)
                        val = PPP_MRU;
                ap->mru = val;
index e6d48e5c65a3379e12bbbd4679b1d0b326d3e93b..4d2ff63f2ee2f6bb02a07419513549890956d32e 100644 (file)
@@ -630,6 +630,7 @@ static void __exit deflate_cleanup(void)
 
 module_init(deflate_init);
 module_exit(deflate_cleanup);
+MODULE_DESCRIPTION("PPP Deflate compression module");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE));
 MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE_DRAFT));
index 0193af2d31c9bcf5dc8864da49ba4e75ba0192fc..3dd52bf28f15bf9f260719f1bf61e45d6d48b3f7 100644 (file)
@@ -3604,6 +3604,7 @@ EXPORT_SYMBOL(ppp_input_error);
 EXPORT_SYMBOL(ppp_output_wakeup);
 EXPORT_SYMBOL(ppp_register_compressor);
 EXPORT_SYMBOL(ppp_unregister_compressor);
+MODULE_DESCRIPTION("Generic PPP layer driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0);
 MODULE_ALIAS_RTNL_LINK("ppp");
index 52d05ce4a2819815963eebf4df399058835ff350..45bf59ac8f5711867ed1ba433d3f5e7800b769e4 100644 (file)
@@ -724,5 +724,6 @@ ppp_sync_cleanup(void)
 
 module_init(ppp_sync_init);
 module_exit(ppp_sync_cleanup);
+MODULE_DESCRIPTION("PPP synchronous TTY channel module");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_LDISC(N_SYNC_PPP);
index 8e7238e97d0a71708ebcddda9b1e1a50ab28c17d..2ea4f4890d23b5f1c5229c7f8b303ee85a954037 100644 (file)
@@ -1007,26 +1007,21 @@ static int pppoe_recvmsg(struct socket *sock, struct msghdr *m,
        struct sk_buff *skb;
        int error = 0;
 
-       if (sk->sk_state & PPPOX_BOUND) {
-               error = -EIO;
-               goto end;
-       }
+       if (sk->sk_state & PPPOX_BOUND)
+               return -EIO;
 
        skb = skb_recv_datagram(sk, flags, &error);
-       if (error < 0)
-               goto end;
+       if (!skb)
+               return error;
 
-       if (skb) {
-               total_len = min_t(size_t, total_len, skb->len);
-               error = skb_copy_datagram_msg(skb, 0, m, total_len);
-               if (error == 0) {
-                       consume_skb(skb);
-                       return total_len;
-               }
+       total_len = min_t(size_t, total_len, skb->len);
+       error = skb_copy_datagram_msg(skb, 0, m, total_len);
+       if (error == 0) {
+               consume_skb(skb);
+               return total_len;
        }
 
        kfree_skb(skb);
-end:
        return error;
 }
 
index 43e0db78d42beccfc2883050bb2665c191e675f8..a742cec44e3db823ae3fa85d6161e20d10dc64fb 100644 (file)
@@ -1803,5 +1803,6 @@ static struct usb_driver ar5523_driver = {
 
 module_usb_driver(ar5523_driver);
 
+MODULE_DESCRIPTION("Atheros AR5523 wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_FIRMWARE(AR5523_FIRMWARE_FILE);
index 41119fb177e306f30280d1a1d83ae5583976668d..4e6b4df8562f632e34089619f7a9b485b5e71595 100644 (file)
@@ -1685,6 +1685,7 @@ static struct platform_driver wcn36xx_driver = {
 
 module_platform_driver(wcn36xx_driver);
 
+MODULE_DESCRIPTION("Qualcomm Atheros WCN3660/3680 wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
 MODULE_FIRMWARE(WLAN_NV_FILE);
index d55f3271d6190234220afd12ac8f6eb7a1d78f64..4f0c1e1a8e605daa4bcf907006bbd8e9a07490fa 100644 (file)
@@ -20,6 +20,7 @@ static void __exit brcmf_bca_exit(void)
        brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_BCA, THIS_MODULE);
 }
 
+MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Broadcom AP chipsets");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_IMPORT_NS(BRCMFMAC);
 
index 133c5ea6429cd0e17baea181209c4d701e662d0c..28d6a30cc0106d6a38b51e35c1f518accfdbe987 100644 (file)
@@ -3779,8 +3779,10 @@ static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
                if (req->channels[i] == chan)
                        break;
        }
-       if (i == req->n_channels)
-               req->channels[req->n_channels++] = chan;
+       if (i == req->n_channels) {
+               req->n_channels++;
+               req->channels[i] = chan;
+       }
 
        for (i = 0; i < req->n_ssids; i++) {
                if (req->ssids[i].ssid_len == ssid_len &&
index f82fbbe3ecefb7af1019281b3f031f45b9ec30e6..90d06cda03a2f007e9f00c636a22a4a130670dff 100644 (file)
@@ -20,6 +20,7 @@ static void __exit brcmf_cyw_exit(void)
        brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_CYW, THIS_MODULE);
 }
 
+MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Cypress/Infineon chipsets");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_IMPORT_NS(BRCMFMAC);
 
index 02918d434556b04d797a4141f3dcaede15a7b494..b66135e3cff476a95c5482e099975fd01849bedf 100644 (file)
@@ -20,6 +20,7 @@ static void __exit brcmf_wcc_exit(void)
        brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_WCC, THIS_MODULE);
 }
 
+MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Broadcom mobility chipsets");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_IMPORT_NS(BRCMFMAC);
 
index b96f30d11644e24eb3886e5f2536d6eaad4d01db..dcc4810cb32472dbe8ee374091a2d58241af80c8 100644 (file)
@@ -618,7 +618,7 @@ int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
                                         &tbl_rev);
        if (!IS_ERR(wifi_pkg)) {
                if (tbl_rev != 2) {
-                       ret = PTR_ERR(wifi_pkg);
+                       ret = -EINVAL;
                        goto out_free;
                }
 
@@ -634,7 +634,7 @@ int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
                                         &tbl_rev);
        if (!IS_ERR(wifi_pkg)) {
                if (tbl_rev != 1) {
-                       ret = PTR_ERR(wifi_pkg);
+                       ret = -EINVAL;
                        goto out_free;
                }
 
@@ -650,7 +650,7 @@ int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
                                         &tbl_rev);
        if (!IS_ERR(wifi_pkg)) {
                if (tbl_rev != 0) {
-                       ret = PTR_ERR(wifi_pkg);
+                       ret = -EINVAL;
                        goto out_free;
                }
 
@@ -707,7 +707,7 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
                                         &tbl_rev);
        if (!IS_ERR(wifi_pkg)) {
                if (tbl_rev != 2) {
-                       ret = PTR_ERR(wifi_pkg);
+                       ret = -EINVAL;
                        goto out_free;
                }
 
@@ -723,7 +723,7 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
                                         &tbl_rev);
        if (!IS_ERR(wifi_pkg)) {
                if (tbl_rev != 1) {
-                       ret = PTR_ERR(wifi_pkg);
+                       ret = -EINVAL;
                        goto out_free;
                }
 
@@ -739,7 +739,7 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
                                         &tbl_rev);
        if (!IS_ERR(wifi_pkg)) {
                if (tbl_rev != 0) {
-                       ret = PTR_ERR(wifi_pkg);
+                       ret = -EINVAL;
                        goto out_free;
                }
 
@@ -1116,6 +1116,9 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
                goto read_table;
        }
 
+       ret = PTR_ERR(wifi_pkg);
+       goto out_free;
+
 read_table:
        fwrt->ppag_ver = tbl_rev;
        flags = &wifi_pkg->package.elements[1];
index 798731ecbefde7f625d0cf00ef688f10281727be..b740c65a7dca25807ac648873a0df14796984d1b 100644 (file)
@@ -537,7 +537,7 @@ enum iwl_fw_dbg_config_cmd_type {
 }; /* LDBG_CFG_CMD_TYPE_API_E_VER_1 */
 
 /* this token disables debug asserts in the firmware */
-#define IWL_FW_DBG_CONFIG_TOKEN 0x00011301
+#define IWL_FW_DBG_CONFIG_TOKEN 0x00010001
 
 /**
  * struct iwl_fw_dbg_config_cmd - configure FW debug
index e27774e7ed74d82bbbb9821f24a2bc3a1578395b..80fda056e46a698458ee4ecf1230f7ef315e3a2a 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2005-2014, 2018-2023 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2024 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
@@ -19,7 +19,6 @@
  * @fwrt_ptr: pointer to the buffer coming from fwrt
  * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
  *     transport's data.
- * @trans_len: length of the valid data in trans_ptr
  * @fwrt_len: length of the valid data in fwrt_ptr
  */
 struct iwl_fw_dump_ptrs {
index ffe2670720c9257c30cd86aa3f5edf7386bce602..abf8001bdac179b7e4b40897182f8b54532d6c97 100644 (file)
@@ -128,6 +128,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
        kfree(drv->fw.ucode_capa.cmd_versions);
        kfree(drv->fw.phy_integration_ver);
        kfree(drv->trans->dbg.pc_data);
+       drv->trans->dbg.pc_data = NULL;
 
        for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
                iwl_free_fw_img(drv, drv->fw.img + i);
index 402896988686990fdd7ea9410f8e01819a7a1bc4..2f6774ec37b2286f1fb72e120a18435e804fcb58 100644 (file)
@@ -668,7 +668,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
                        .has_eht = true,
                        .eht_cap_elem = {
                                .mac_cap_info[0] =
-                                       IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
                                        IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
                                        IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
                                        IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 |
@@ -793,7 +792,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
                        .has_eht = true,
                        .eht_cap_elem = {
                                .mac_cap_info[0] =
-                                       IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
                                        IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
                                        IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
                                        IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2,
@@ -1020,8 +1018,7 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
        if (CSR_HW_REV_TYPE(trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
            iftype_data->eht_cap.has_eht) {
                iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &=
-                       ~(IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
-                         IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
+                       ~(IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
                          IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2);
                iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &=
                        ~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
index 7f13dff04b265caf265f24662d7609f60289120d..53e26c3c3a9af616ac057428503edf6270d53b3d 100644 (file)
@@ -1600,7 +1600,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
         */
        if (vif->type == NL80211_IFTYPE_AP ||
            vif->type == NL80211_IFTYPE_ADHOC) {
-               iwl_mvm_vif_dbgfs_add_link(mvm, vif);
+               if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+                       iwl_mvm_vif_dbgfs_add_link(mvm, vif);
                ret = 0;
                goto out;
        }
@@ -1640,7 +1641,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
                        iwl_mvm_chandef_get_primary_80(&vif->bss_conf.chandef);
        }
 
-       iwl_mvm_vif_dbgfs_add_link(mvm, vif);
+       if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+               iwl_mvm_vif_dbgfs_add_link(mvm, vif);
 
        if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
            vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
@@ -3685,6 +3687,9 @@ iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
                                           NL80211_TDLS_SETUP);
        }
 
+       if (ret)
+               return ret;
+
        for_each_sta_active_link(vif, sta, link_sta, i)
                link_sta->agg.max_rc_amsdu_len = 1;
 
index 61170173f917a00707fc63956b8d7f252737c809..893b69fc841b896b234078240631d72c792a4c7e 100644 (file)
@@ -81,7 +81,8 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
                ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
        }
 
-       iwl_mvm_vif_dbgfs_add_link(mvm, vif);
+       if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+               iwl_mvm_vif_dbgfs_add_link(mvm, vif);
 
        if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
            vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
@@ -437,6 +438,9 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
                mvmvif->ap_ibss_active = false;
        }
 
+       iwl_mvm_link_changed(mvm, vif, link_conf,
+                            LINK_CONTEXT_MODIFY_ACTIVE, false);
+
        if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
                int ret = iwl_mvm_esr_mode_inactive(mvm, vif);
 
@@ -448,9 +452,6 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
        if (vif->type == NL80211_IFTYPE_MONITOR)
                iwl_mvm_mld_rm_snif_sta(mvm, vif);
 
-       iwl_mvm_link_changed(mvm, vif, link_conf,
-                            LINK_CONTEXT_MODIFY_ACTIVE, false);
-
        if (switching_chanctx)
                return;
        mvmvif->link[link_id]->phy_ctxt = NULL;
index 886d0009852872a5fc91a5f2f11476b3fdda78d8..af15d470c69bd60ea3737753b70832b9ffcf7d7f 100644 (file)
@@ -505,6 +505,10 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
                return false;
 
        mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+
+       if (WARN_ON_ONCE(!mvm_sta->dup_data))
+               return false;
+
        dup_data = &mvm_sta->dup_data[queue];
 
        /*
index 218fdf1ed5304f333008c8015ae796ff59583db0..2e653a417d6269b333ec12e7d15f43f3c66be46b 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2017 Intel Deutschland GmbH
  */
@@ -972,6 +972,7 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
        if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) {
                /* End TE, notify mac80211 */
                mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID;
+               mvmvif->time_event_data.link_id = -1;
                iwl_mvm_p2p_roc_finished(mvm);
                ieee80211_remain_on_channel_expired(mvm->hw);
        } else if (le32_to_cpu(notif->start)) {
index db986bfc4dc3fe4374e22b071ecbf178fbb796dd..461f26d9214e4ab81e32033c00629b92f7e31700 100644 (file)
@@ -520,13 +520,24 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
        }
 }
 
+static void iwl_mvm_copy_hdr(void *cmd, const void *hdr, int hdrlen,
+                            const u8 *addr3_override)
+{
+       struct ieee80211_hdr *out_hdr = cmd;
+
+       memcpy(cmd, hdr, hdrlen);
+       if (addr3_override)
+               memcpy(out_hdr->addr3, addr3_override, ETH_ALEN);
+}
+
 /*
  * Allocates and sets the Tx cmd the driver data pointers in the skb
  */
 static struct iwl_device_tx_cmd *
 iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
                      struct ieee80211_tx_info *info, int hdrlen,
-                     struct ieee80211_sta *sta, u8 sta_id)
+                     struct ieee80211_sta *sta, u8 sta_id,
+                     const u8 *addr3_override)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct iwl_device_tx_cmd *dev_cmd;
@@ -584,7 +595,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
                        cmd->len = cpu_to_le16((u16)skb->len);
 
                        /* Copy MAC header from skb into command buffer */
-                       memcpy(cmd->hdr, hdr, hdrlen);
+                       iwl_mvm_copy_hdr(cmd->hdr, hdr, hdrlen, addr3_override);
 
                        cmd->flags = cpu_to_le16(flags);
                        cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
@@ -599,7 +610,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
                        cmd->len = cpu_to_le16((u16)skb->len);
 
                        /* Copy MAC header from skb into command buffer */
-                       memcpy(cmd->hdr, hdr, hdrlen);
+                       iwl_mvm_copy_hdr(cmd->hdr, hdr, hdrlen, addr3_override);
 
                        cmd->flags = cpu_to_le32(flags);
                        cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
@@ -617,7 +628,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
        iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control);
 
        /* Copy MAC header from skb into command buffer */
-       memcpy(tx_cmd->hdr, hdr, hdrlen);
+       iwl_mvm_copy_hdr(tx_cmd->hdr, hdr, hdrlen, addr3_override);
 
 out:
        return dev_cmd;
@@ -820,7 +831,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
 
        IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, queue);
 
-       dev_cmd = iwl_mvm_set_tx_params(mvm, skb, &info, hdrlen, NULL, sta_id);
+       dev_cmd = iwl_mvm_set_tx_params(mvm, skb, &info, hdrlen, NULL, sta_id,
+                                       NULL);
        if (!dev_cmd)
                return -1;
 
@@ -1140,7 +1152,8 @@ static int iwl_mvm_tx_pkt_queued(struct iwl_mvm *mvm,
  */
 static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
                           struct ieee80211_tx_info *info,
-                          struct ieee80211_sta *sta)
+                          struct ieee80211_sta *sta,
+                          const u8 *addr3_override)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct iwl_mvm_sta *mvmsta;
@@ -1172,7 +1185,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
                iwl_mvm_probe_resp_set_noa(mvm, skb);
 
        dev_cmd = iwl_mvm_set_tx_params(mvm, skb, info, hdrlen,
-                                       sta, mvmsta->deflink.sta_id);
+                                       sta, mvmsta->deflink.sta_id,
+                                       addr3_override);
        if (!dev_cmd)
                goto drop;
 
@@ -1294,9 +1308,11 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct ieee80211_tx_info info;
        struct sk_buff_head mpdus_skbs;
+       struct ieee80211_vif *vif;
        unsigned int payload_len;
        int ret;
        struct sk_buff *orig_skb = skb;
+       const u8 *addr3;
 
        if (WARN_ON_ONCE(!mvmsta))
                return -1;
@@ -1307,26 +1323,59 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
        memcpy(&info, skb->cb, sizeof(info));
 
        if (!skb_is_gso(skb))
-               return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
+               return iwl_mvm_tx_mpdu(mvm, skb, &info, sta, NULL);
 
        payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) -
                tcp_hdrlen(skb) + skb->data_len;
 
        if (payload_len <= skb_shinfo(skb)->gso_size)
-               return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
+               return iwl_mvm_tx_mpdu(mvm, skb, &info, sta, NULL);
 
        __skb_queue_head_init(&mpdus_skbs);
 
+       vif = info.control.vif;
+       if (!vif)
+               return -1;
+
        ret = iwl_mvm_tx_tso(mvm, skb, &info, sta, &mpdus_skbs);
        if (ret)
                return ret;
 
        WARN_ON(skb_queue_empty(&mpdus_skbs));
 
+       /*
+        * As described in IEEE sta 802.11-2020, table 9-30 (Address
+        * field contents), A-MSDU address 3 should contain the BSSID
+        * address.
+        * Pass address 3 down to iwl_mvm_tx_mpdu() and further to set it
+        * in the command header. We need to preserve the original
+        * address 3 in the skb header to correctly create all the
+        * A-MSDU subframe headers from it.
+        */
+       switch (vif->type) {
+       case NL80211_IFTYPE_STATION:
+               addr3 = vif->cfg.ap_addr;
+               break;
+       case NL80211_IFTYPE_AP:
+               addr3 = vif->addr;
+               break;
+       default:
+               addr3 = NULL;
+               break;
+       }
+
        while (!skb_queue_empty(&mpdus_skbs)) {
+               struct ieee80211_hdr *hdr;
+               bool amsdu;
+
                skb = __skb_dequeue(&mpdus_skbs);
+               hdr = (void *)skb->data;
+               amsdu = ieee80211_is_data_qos(hdr->frame_control) &&
+                       (*ieee80211_get_qos_ctl(hdr) &
+                        IEEE80211_QOS_CTL_A_MSDU_PRESENT);
 
-               ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
+               ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta,
+                                     amsdu ? addr3 : NULL);
                if (ret) {
                        /* Free skbs created as part of TSO logic that have not yet been dequeued */
                        __skb_queue_purge(&mpdus_skbs);
index ce0179b8ab368fa7138a394afbc32678b05d20fc..0073b5e0f9c90ba473e71f1902724d8979bdc792 100644 (file)
@@ -700,6 +700,7 @@ static struct spi_driver p54spi_driver = {
 
 module_spi_driver(p54spi_driver);
 
+MODULE_DESCRIPTION("Prism54 SPI wireless driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
 MODULE_ALIAS("spi:cx3110x");
index 89d738deea62e9ed4d4f9044e1a193548833deff..e2146d30e55363ecdfec2ed26bb7753384f04317 100644 (file)
@@ -728,6 +728,7 @@ const struct ieee80211_ops mt7603_ops = {
        .set_sar_specs = mt7603_set_sar_specs,
 };
 
+MODULE_DESCRIPTION("MediaTek MT7603E and MT76x8 wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
 
 static int __init mt7603_init(void)
index dab16b5fc3861198f9eccd3ae48c776bb03a66a1..0971c164b57e926d2d22dd1ef4f0559d45420db2 100644 (file)
@@ -1375,4 +1375,5 @@ const struct ieee80211_ops mt7615_ops = {
 };
 EXPORT_SYMBOL_GPL(mt7615_ops);
 
+MODULE_DESCRIPTION("MediaTek MT7615E and MT7663E wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
index ac036a072439d5d0a2c7eb8aad38048b4098b25f..87a956ea3ad74f6fb62a873eba0f499e04a99c32 100644 (file)
@@ -270,4 +270,5 @@ static void __exit mt7615_exit(void)
 
 module_init(mt7615_init);
 module_exit(mt7615_exit);
+MODULE_DESCRIPTION("MediaTek MT7615E MMIO helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index 67cedd2555f973fc53cd0e37312771c3e0fa1116..9692890ba51b7b61c43991cb20a59d8394188c1e 100644 (file)
@@ -253,4 +253,5 @@ module_sdio_driver(mt7663s_driver);
 
 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
+MODULE_DESCRIPTION("MediaTek MT7663S (SDIO) wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
index 04963b9f749838c41717884ecb818e9d0894667b..df737e1ff27b79a21c1b92ca899272eb961800f0 100644 (file)
@@ -281,4 +281,5 @@ module_usb_driver(mt7663u_driver);
 
 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
+MODULE_DESCRIPTION("MediaTek MT7663U (USB) wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
index 0052d103e276a895e3eddb81edb4397e0149281b..820b395900275a700da43e7139c3a22effa17140 100644 (file)
@@ -349,4 +349,5 @@ EXPORT_SYMBOL_GPL(mt7663_usb_sdio_register_device);
 
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek MT7663 SDIO/USB helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index 96494ba2fdf767ba89d25b505ca7ee86b0797c19..3a20ba0d2492840304f9f5b108a8f82643ce7396 100644 (file)
@@ -3160,4 +3160,5 @@ exit:
 EXPORT_SYMBOL_GPL(mt76_connac2_mcu_fill_message);
 
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
+MODULE_DESCRIPTION("MediaTek MT76x connac layer helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index c3a392a1a659e8a0581809a3a5e03d9847085496..bcd24c9072ec9e52f68c7dac0f124279d525eba0 100644 (file)
@@ -342,4 +342,5 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev)
        return 0;
 }
 
+MODULE_DESCRIPTION("MediaTek MT76x EEPROM helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index 9277ff38b7a228fd778e8c9909eed0182eb14306..293e66fa83d5d0669d4f26acaff150a41f35debc 100644 (file)
@@ -302,6 +302,7 @@ static const struct pci_device_id mt76x0e_device_table[] = {
 MODULE_DEVICE_TABLE(pci, mt76x0e_device_table);
 MODULE_FIRMWARE(MT7610E_FIRMWARE);
 MODULE_FIRMWARE(MT7650E_FIRMWARE);
+MODULE_DESCRIPTION("MediaTek MT76x0E (PCIe) wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
 
 static struct pci_driver mt76x0e_driver = {
index 0422c332354a131dab040c72a8961ec6f1b79515..dd042949cf82bc6c87f4aaee8b7c5d912faf2162 100644 (file)
@@ -336,6 +336,7 @@ err:
 MODULE_DEVICE_TABLE(usb, mt76x0_device_table);
 MODULE_FIRMWARE(MT7610E_FIRMWARE);
 MODULE_FIRMWARE(MT7610U_FIRMWARE);
+MODULE_DESCRIPTION("MediaTek MT76x0U (USB) wireless driver");
 MODULE_LICENSE("GPL");
 
 static struct usb_driver mt76x0_driver = {
index 02da543dfc5cf381f6edac1753c0d627504e3e48..b2cc449142945f585a7d50ca0d68da21e35531e7 100644 (file)
@@ -293,4 +293,5 @@ void mt76x02u_init_mcu(struct mt76_dev *dev)
 EXPORT_SYMBOL_GPL(mt76x02u_init_mcu);
 
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
+MODULE_DESCRIPTION("MediaTek MT76x02 MCU helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index 8a0e8124b894003ed80aad02ff6c59be9f3e457f..8020446be37bd99c15b9410b697060a304ef18af 100644 (file)
@@ -696,4 +696,5 @@ void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mt76x02_config_mac_addr_list);
 
+MODULE_DESCRIPTION("MediaTek MT76x02 helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index 8c01855885ce3949a16e63fe4169db3345a62044..1fe5f5a02f937783c669205e286e917ec0872db1 100644 (file)
@@ -506,4 +506,5 @@ int mt76x2_eeprom_init(struct mt76x02_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mt76x2_eeprom_init);
 
+MODULE_DESCRIPTION("MediaTek MT76x2 EEPROM helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index df85ebc6e1df07a7c2e48c30efa50cdeec9f993f..30959746e9242712e8196724157db8c93caa96f3 100644 (file)
@@ -165,6 +165,7 @@ mt76x2e_resume(struct pci_dev *pdev)
 MODULE_DEVICE_TABLE(pci, mt76x2e_device_table);
 MODULE_FIRMWARE(MT7662_FIRMWARE);
 MODULE_FIRMWARE(MT7662_ROM_PATCH);
+MODULE_DESCRIPTION("MediaTek MT76x2E (PCIe) wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
 
 static struct pci_driver mt76pci_driver = {
index 55068f3252ef341f4fbdc6d7dd382296e47b17f7..ca78e14251c2f5cda524c046b9c80a96b4481167 100644 (file)
@@ -147,4 +147,5 @@ static struct usb_driver mt76x2u_driver = {
 module_usb_driver(mt76x2u_driver);
 
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
+MODULE_DESCRIPTION("MediaTek MT76x2U (USB) wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
index aff4f21e843d29ae24b1ef094b407e344597bf36..3039f53e224546a406a2fc4cc0b2f8e07884d456 100644 (file)
@@ -958,4 +958,5 @@ static void __exit mt7915_exit(void)
 
 module_init(mt7915_init);
 module_exit(mt7915_exit);
+MODULE_DESCRIPTION("MediaTek MT7915E MMIO helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index 0645417e05825f709e19e392e48544d36d2e3534..0d5adc5ddae38283eb618ba00284fb4b527c677c 100644 (file)
@@ -1418,5 +1418,6 @@ const struct ieee80211_ops mt7921_ops = {
 };
 EXPORT_SYMBOL_GPL(mt7921_ops);
 
+MODULE_DESCRIPTION("MediaTek MT7921 core driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
index 57903c6e4f11f0735fd80c4a3c54c4299ca48be0..dde26f3274783d9a7dc84da9be5e8fa214fba21e 100644 (file)
@@ -544,4 +544,5 @@ MODULE_FIRMWARE(MT7922_FIRMWARE_WM);
 MODULE_FIRMWARE(MT7922_ROM_PATCH);
 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
+MODULE_DESCRIPTION("MediaTek MT7921E (PCIe) wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
index 7591e54d289733472740a5afe747833070363f2e..a9ce1e746b954bc7c7599f23ec6a6c23031dd384 100644 (file)
@@ -323,5 +323,6 @@ static struct sdio_driver mt7921s_driver = {
        .drv.pm         = pm_sleep_ptr(&mt7921s_pm_ops),
 };
 module_sdio_driver(mt7921s_driver);
+MODULE_DESCRIPTION("MediaTek MT7921S (SDIO) wireless driver");
 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
 MODULE_LICENSE("Dual BSD/GPL");
index e5258c74fc077ac69b310b5bab0e56c02ebfcef5..8b7c03c47598de7bf9037ed40cb370607a837af4 100644 (file)
@@ -336,5 +336,6 @@ static struct usb_driver mt7921u_driver = {
 };
 module_usb_driver(mt7921u_driver);
 
+MODULE_DESCRIPTION("MediaTek MT7921U (USB) wireless driver");
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
 MODULE_LICENSE("Dual BSD/GPL");
index 8f1075da4903908b5f149e12530d21f6735be07f..125a1be3cb64c6a1a14bb6aaac28ec0fbc11e889 100644 (file)
@@ -1450,4 +1450,5 @@ const struct ieee80211_ops mt7925_ops = {
 EXPORT_SYMBOL_GPL(mt7925_ops);
 
 MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek MT7925 core driver");
 MODULE_LICENSE("Dual BSD/GPL");
index 734f31ee40d3f740873dc0c53356a63fa11ff976..1fd99a856541589b1f3859795e8b23bcc0c06cdf 100644 (file)
@@ -583,4 +583,5 @@ MODULE_FIRMWARE(MT7925_FIRMWARE_WM);
 MODULE_FIRMWARE(MT7925_ROM_PATCH);
 MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>");
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
+MODULE_DESCRIPTION("MediaTek MT7925E (PCIe) wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
index 9b885c5b3ed594ddc9c5b62f47dfd4522430f469..1e0f094fc9059dbb02585bdc168b6b763f198004 100644 (file)
@@ -329,4 +329,5 @@ static struct usb_driver mt7925u_driver = {
 module_usb_driver(mt7925u_driver);
 
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
+MODULE_DESCRIPTION("MediaTek MT7925U (USB) wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
index 502be22dbe3677fb475371b7e4c564be074899d8..c42101aa9e45e958f605e37e763bb090c63aeea5 100644 (file)
@@ -862,5 +862,6 @@ int mt792x_load_firmware(struct mt792x_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mt792x_load_firmware);
 
+MODULE_DESCRIPTION("MediaTek MT792x core driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
index 2dd283caed36bf056127d17a6cd3e93e9f6664d4..589a3efb9f8c30bbce14ec288e8ad66ecf0acf99 100644 (file)
@@ -314,5 +314,6 @@ void mt792xu_disconnect(struct usb_interface *usb_intf)
 }
 EXPORT_SYMBOL_GPL(mt792xu_disconnect);
 
+MODULE_DESCRIPTION("MediaTek MT792x USB helpers");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
index 3c729b563edc5dd6f964e0e72c46f276367c3d65..699be57309c2e4db6d8ff3f456d55fe5a75be291 100644 (file)
@@ -4477,7 +4477,8 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
 
        skb_put_data(skb, &req, sizeof(req));
        /* cck and ofdm */
-       skb_put_data(skb, &la.cck, sizeof(la.cck) + sizeof(la.ofdm));
+       skb_put_data(skb, &la.cck, sizeof(la.cck));
+       skb_put_data(skb, &la.ofdm, sizeof(la.ofdm));
        /* ht20 */
        skb_put_data(skb, &la.mcs[0], 8);
        /* ht40 */
index c50d89a445e9560672aeab8752de112220c9ab1c..9f2abfa273c9b060a793ae2594963f5c123fc5b0 100644 (file)
@@ -650,4 +650,5 @@ static void __exit mt7996_exit(void)
 
 module_init(mt7996_init);
 module_exit(mt7996_exit);
+MODULE_DESCRIPTION("MediaTek MT7996 MMIO helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index c52d550f0c32aac260e3163f14ec4989efbacc53..3e88798df0178c17cce2e94f588feb43711ad0a0 100644 (file)
@@ -672,4 +672,5 @@ EXPORT_SYMBOL_GPL(mt76s_init);
 
 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
+MODULE_DESCRIPTION("MediaTek MT76x SDIO helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index 1584665fe3cb68d890bd7606e3eedcd05a470a2c..5a0bcb5071bd7d5ee8c22ef54ad3e05b3ea96cf4 100644 (file)
@@ -1128,4 +1128,5 @@ int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf)
 EXPORT_SYMBOL_GPL(mt76u_init);
 
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
+MODULE_DESCRIPTION("MediaTek MT76x USB helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index fc76c66ff1a5a58f1c73e9ff50ceeea4926b8063..d6c01a2dd1988c5a9ef50bc96ceb0e30b453302d 100644 (file)
@@ -138,4 +138,5 @@ int __mt76_worker_fn(void *ptr)
 }
 EXPORT_SYMBOL_GPL(__mt76_worker_fn);
 
+MODULE_DESCRIPTION("MediaTek MT76x helpers");
 MODULE_LICENSE("Dual BSD/GPL");
index 91d71e0f7ef2332354a0b950eea3e8795387ed7b..81e8f25863f5bdc957fa5b4ee53a78c31f81eba6 100644 (file)
@@ -1018,5 +1018,6 @@ unregister_netdev:
        return ERR_PTR(ret);
 }
 
+MODULE_DESCRIPTION("Atmel WILC1000 core wireless driver");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(WILC1000_FW(WILC1000_API_VER));
index 0d13e3e46e98e4b59852811324792793fc27f78e..d6d3946930905275ba021611307d6a16324a0bb8 100644 (file)
@@ -984,4 +984,5 @@ static struct sdio_driver wilc_sdio_driver = {
 module_driver(wilc_sdio_driver,
              sdio_register_driver,
              sdio_unregister_driver);
+MODULE_DESCRIPTION("Atmel WILC1000 SDIO wireless driver");
 MODULE_LICENSE("GPL");
index 77b4cdff73c370bf1bbd1e1ebec77eb0cac318b7..1d8b241ce43cae3329eb9fee84afc63a1027447e 100644 (file)
@@ -273,6 +273,7 @@ static struct spi_driver wilc_spi_driver = {
        .remove = wilc_bus_remove,
 };
 module_spi_driver(wilc_spi_driver);
+MODULE_DESCRIPTION("Atmel WILC1000 SPI wireless driver");
 MODULE_LICENSE("GPL");
 
 static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len)
index 301bd0043a4354032ceac6c45768c347b473163b..4e5b351f80f0922cabc3f1ce57fa44960c090e3c 100644 (file)
@@ -343,5 +343,6 @@ static void __exit wl1251_sdio_exit(void)
 module_init(wl1251_sdio_init);
 module_exit(wl1251_sdio_exit);
 
+MODULE_DESCRIPTION("TI WL1251 SDIO helpers");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
index 29292f06bd3dcb191bee70af1b295a6a62abf841..1936bb3af54ab6509edff7a6afdf23f9e9a9b728 100644 (file)
@@ -342,6 +342,7 @@ static struct spi_driver wl1251_spi_driver = {
 
 module_spi_driver(wl1251_spi_driver);
 
+MODULE_DESCRIPTION("TI WL1251 SPI helpers");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
 MODULE_ALIAS("spi:wl1251");
index de045fe4ca1eb982105a4a7a2d502f142efd5d02..b26d42b4e3cc0fbdc21e55b4b9682b0a81e1ec8e 100644 (file)
@@ -1955,6 +1955,7 @@ module_param_named(tcxo, tcxo_param, charp, 0);
 MODULE_PARM_DESC(tcxo,
                 "TCXO clock: 19.2, 26, 38.4, 52, 16.368, 32.736, 16.8, 33.6");
 
+MODULE_DESCRIPTION("TI WL12xx wireless driver");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
index 20d9181b3410c40b555d7f06836469357782fc9f..2ccac1cdec0120c1709d09add0bcdf390f57e7e7 100644 (file)
@@ -2086,6 +2086,7 @@ module_param_named(num_rx_desc, num_rx_desc_param, int, 0400);
 MODULE_PARM_DESC(num_rx_desc_param,
                 "Number of Rx descriptors: u8 (default is 32)");
 
+MODULE_DESCRIPTION("TI WiLink 8 wireless driver");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_FIRMWARE(WL18XX_FW_NAME);
index fb9ed97774c7a29ab1a27689f7e78bf3740c0c3f..5736acb4d2063cbd1ca9f9f23187102d1d30c599 100644 (file)
@@ -6793,6 +6793,7 @@ MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
 module_param(no_recovery, int, 0600);
 MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck.");
 
+MODULE_DESCRIPTION("TI WLAN core driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
index f0686635db46e1246f3d06a8814f50d4c93c85ff..eb5482ed76ae48488ef5f55d1731c080c25b9919 100644 (file)
@@ -447,6 +447,7 @@ module_sdio_driver(wl1271_sdio_driver);
 module_param(dump, bool, 0600);
 MODULE_PARM_DESC(dump, "Enable sdio read/write dumps.");
 
+MODULE_DESCRIPTION("TI WLAN SDIO helpers");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
index 7d9a139db59e1552e3f4cd6feae526c4a5211e69..0aa2b2f3c5c914160d05198c3fc8c6ed07c6e999 100644 (file)
@@ -562,6 +562,7 @@ static struct spi_driver wl1271_spi_driver = {
 };
 
 module_spi_driver(wl1271_spi_driver);
+MODULE_DESCRIPTION("TI WLAN SPI helpers");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
index fab361a250d6054e03a40e451efda2eb3678fda6..ef76850d9bcd232e84f00c4576c5a98ace51458f 100644 (file)
@@ -1778,5 +1778,6 @@ static void __exit netback_fini(void)
 }
 module_exit(netback_fini);
 
+MODULE_DESCRIPTION("Xen backend network device module");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_ALIAS("xen-backend:vif");
index 0d124a8ca9c321700844bbb8ccc176a6c3081189..0a96362912ceda0a035b916f432b24afb261f6a7 100644 (file)
@@ -713,7 +713,7 @@ void nvme_init_request(struct request *req, struct nvme_command *cmd)
        if (req->q->queuedata) {
                struct nvme_ns *ns = req->q->disk->private_data;
 
-               logging_enabled = ns->passthru_err_log_enabled;
+               logging_enabled = ns->head->passthru_err_log_enabled;
                req->timeout = NVME_IO_TIMEOUT;
        } else { /* no queuedata implies admin queue */
                logging_enabled = nr->ctrl->passthru_err_log_enabled;
@@ -1153,6 +1153,10 @@ u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode)
                effects &= ~NVME_CMD_EFFECTS_CSE_MASK;
        } else {
                effects = le32_to_cpu(ctrl->effects->acs[opcode]);
+
+               /* Ignore execution restrictions if any relaxation bits are set */
+               if (effects & NVME_CMD_EFFECTS_CSER_MASK)
+                       effects &= ~NVME_CMD_EFFECTS_CSE_MASK;
        }
 
        return effects;
@@ -3696,7 +3700,6 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
 
        ns->disk = disk;
        ns->queue = disk->queue;
-       ns->passthru_err_log_enabled = false;
 
        if (ctrl->opts && ctrl->opts->data_digest)
                blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, ns->queue);
@@ -3762,8 +3765,8 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
 
        /*
         * Set ns->disk->device->driver_data to ns so we can access
-        * ns->logging_enabled in nvme_passthru_err_log_enabled_store() and
-        * nvme_passthru_err_log_enabled_show().
+        * ns->head->passthru_err_log_enabled in
+        * nvme_io_passthru_err_log_enabled_[store | show]().
         */
        dev_set_drvdata(disk_to_dev(ns->disk), ns);
 
@@ -4191,6 +4194,7 @@ static bool nvme_ctrl_pp_status(struct nvme_ctrl *ctrl)
 static void nvme_get_fw_slot_info(struct nvme_ctrl *ctrl)
 {
        struct nvme_fw_slot_info_log *log;
+       u8 next_fw_slot, cur_fw_slot;
 
        log = kmalloc(sizeof(*log), GFP_KERNEL);
        if (!log)
@@ -4202,13 +4206,15 @@ static void nvme_get_fw_slot_info(struct nvme_ctrl *ctrl)
                goto out_free_log;
        }
 
-       if (log->afi & 0x70 || !(log->afi & 0x7)) {
+       cur_fw_slot = log->afi & 0x7;
+       next_fw_slot = (log->afi & 0x70) >> 4;
+       if (!cur_fw_slot || (next_fw_slot && (cur_fw_slot != next_fw_slot))) {
                dev_info(ctrl->device,
                         "Firmware is activated after next Controller Level Reset\n");
                goto out_free_log;
        }
 
-       memcpy(ctrl->subsys->firmware_rev, &log->frs[(log->afi & 0x7) - 1],
+       memcpy(ctrl->subsys->firmware_rev, &log->frs[cur_fw_slot - 1],
                sizeof(ctrl->subsys->firmware_rev));
 
 out_free_log:
index 3499acbf6a822fc1a45d93894f4870a9a5f7857c..495c171daead11395a97de82901b5b71662f8f17 100644 (file)
@@ -534,6 +534,7 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
        if (ret) {
                nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32),
                                       &cmd, data);
+               goto out_free_data;
        }
        result = le32_to_cpu(res.u32);
        if (result & (NVME_CONNECT_AUTHREQ_ATR | NVME_CONNECT_AUTHREQ_ASCR)) {
index 18f5c1be5d67e50ecef131bfe5b223e4e5eda5bd..3dfd5ae99ae05e892eb793cb3b21ba0b75dd6e98 100644 (file)
@@ -228,7 +228,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
        length = (io.nblocks + 1) << ns->head->lba_shift;
 
        if ((io.control & NVME_RW_PRINFO_PRACT) &&
-           ns->head->ms == sizeof(struct t10_pi_tuple)) {
+           (ns->head->ms == ns->head->pi_size)) {
                /*
                 * Protection information is stripped/inserted by the
                 * controller.
index 3897334e3950d5f2de1451961a159708cf4b8077..7b87763e2f8a69f5edef68e2e657ed417e911cb8 100644 (file)
@@ -455,6 +455,7 @@ struct nvme_ns_head {
        struct list_head        entry;
        struct kref             ref;
        bool                    shared;
+       bool                    passthru_err_log_enabled;
        int                     instance;
        struct nvme_effects_log *effects;
        u64                     nuse;
@@ -523,7 +524,6 @@ struct nvme_ns {
        struct device           cdev_device;
 
        struct nvme_fault_inject fault_inject;
-       bool                    passthru_err_log_enabled;
 };
 
 /* NVMe ns supports metadata actions by the controller (generate/strip) */
index d099218e494a8457d546ee0e330b2095e7b9d9fc..f2832f70e7e0a861070d066bf1ee71c19fbf5ae2 100644 (file)
@@ -48,8 +48,8 @@ static ssize_t nvme_adm_passthru_err_log_enabled_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
        struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-       int err;
        bool passthru_err_log_enabled;
+       int err;
 
        err = kstrtobool(buf, &passthru_err_log_enabled);
        if (err)
@@ -60,25 +60,34 @@ static ssize_t nvme_adm_passthru_err_log_enabled_store(struct device *dev,
        return count;
 }
 
+static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev)
+{
+       struct gendisk *disk = dev_to_disk(dev);
+
+       if (nvme_disk_is_ns_head(disk))
+               return disk->private_data;
+       return nvme_get_ns_from_dev(dev)->head;
+}
+
 static ssize_t nvme_io_passthru_err_log_enabled_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
-       struct nvme_ns *n = dev_get_drvdata(dev);
+       struct nvme_ns_head *head = dev_to_ns_head(dev);
 
-       return sysfs_emit(buf, n->passthru_err_log_enabled ? "on\n" : "off\n");
+       return sysfs_emit(buf, head->passthru_err_log_enabled ? "on\n" : "off\n");
 }
 
 static ssize_t nvme_io_passthru_err_log_enabled_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct nvme_ns *ns = dev_get_drvdata(dev);
-       int err;
+       struct nvme_ns_head *head = dev_to_ns_head(dev);
        bool passthru_err_log_enabled;
+       int err;
 
        err = kstrtobool(buf, &passthru_err_log_enabled);
        if (err)
                return -EINVAL;
-       ns->passthru_err_log_enabled = passthru_err_log_enabled;
+       head->passthru_err_log_enabled = passthru_err_log_enabled;
 
        return count;
 }
@@ -91,15 +100,6 @@ static struct device_attribute dev_attr_io_passthru_err_log_enabled = \
        __ATTR(passthru_err_log_enabled, S_IRUGO | S_IWUSR, \
        nvme_io_passthru_err_log_enabled_show, nvme_io_passthru_err_log_enabled_store);
 
-static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev)
-{
-       struct gendisk *disk = dev_to_disk(dev);
-
-       if (nvme_disk_is_ns_head(disk))
-               return disk->private_data;
-       return nvme_get_ns_from_dev(dev)->head;
-}
-
 static ssize_t wwid_show(struct device *dev, struct device_attribute *attr,
                char *buf)
 {
index d8da840a1c0ed1e9c383d59c11227f7fddfe607d..9964ffe347d2ada3cca88e517d294205e77d29ab 100644 (file)
@@ -209,7 +209,7 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
        struct nvmf_connect_command *c = &req->cmd->connect;
        struct nvmf_connect_data *d;
        struct nvmet_ctrl *ctrl = NULL;
-       u16 status = 0;
+       u16 status;
        int ret;
 
        if (!nvmet_check_transfer_len(req, sizeof(struct nvmf_connect_data)))
@@ -290,7 +290,7 @@ static void nvmet_execute_io_connect(struct nvmet_req *req)
        struct nvmf_connect_data *d;
        struct nvmet_ctrl *ctrl;
        u16 qid = le16_to_cpu(c->qid);
-       u16 status = 0;
+       u16 status;
 
        if (!nvmet_check_transfer_len(req, sizeof(struct nvmf_connect_data)))
                return;
index 641a40cf5cf34a7d0aa3bf94362a95ae58065fe1..b71267c6667cf80309532c4ca2602354ccfc34a2 100644 (file)
@@ -763,7 +763,9 @@ struct device_node *of_graph_get_port_parent(struct device_node *node)
        /* Walk 3 levels up only if there is 'ports' node. */
        for (depth = 3; depth && node; depth--) {
                node = of_get_next_parent(node);
-               if (depth == 2 && !of_node_name_eq(node, "ports"))
+               if (depth == 2 && !of_node_name_eq(node, "ports") &&
+                   !of_node_name_eq(node, "in-ports") &&
+                   !of_node_name_eq(node, "out-ports"))
                        break;
        }
        return node;
@@ -1063,36 +1065,6 @@ of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
        return of_device_get_match_data(dev);
 }
 
-static struct device_node *of_get_compat_node(struct device_node *np)
-{
-       of_node_get(np);
-
-       while (np) {
-               if (!of_device_is_available(np)) {
-                       of_node_put(np);
-                       np = NULL;
-               }
-
-               if (of_property_present(np, "compatible"))
-                       break;
-
-               np = of_get_next_parent(np);
-       }
-
-       return np;
-}
-
-static struct device_node *of_get_compat_node_parent(struct device_node *np)
-{
-       struct device_node *parent, *node;
-
-       parent = of_get_parent(np);
-       node = of_get_compat_node(parent);
-       of_node_put(parent);
-
-       return node;
-}
-
 static void of_link_to_phandle(struct device_node *con_np,
                              struct device_node *sup_np)
 {
@@ -1222,10 +1194,10 @@ static struct device_node *parse_##fname(struct device_node *np,             \
  *  parse_prop.prop_name: Name of property holding a phandle value
  *  parse_prop.index: For properties holding a list of phandles, this is the
  *                   index into the list
+ * @get_con_dev: If the consumer node containing the property is never converted
+ *              to a struct device, implement this ops so fw_devlink can use it
+ *              to find the true consumer.
  * @optional: Describes whether a supplier is mandatory or not
- * @node_not_dev: The consumer node containing the property is never converted
- *               to a struct device. Instead, parse ancestor nodes for the
- *               compatible property to find a node corresponding to a device.
  *
  * Returns:
  * parse_prop() return values are
@@ -1236,15 +1208,15 @@ static struct device_node *parse_##fname(struct device_node *np,             \
 struct supplier_bindings {
        struct device_node *(*parse_prop)(struct device_node *np,
                                          const char *prop_name, int index);
+       struct device_node *(*get_con_dev)(struct device_node *np);
        bool optional;
-       bool node_not_dev;
 };
 
 DEFINE_SIMPLE_PROP(clocks, "clocks", "#clock-cells")
 DEFINE_SIMPLE_PROP(interconnects, "interconnects", "#interconnect-cells")
 DEFINE_SIMPLE_PROP(iommus, "iommus", "#iommu-cells")
 DEFINE_SIMPLE_PROP(mboxes, "mboxes", "#mbox-cells")
-DEFINE_SIMPLE_PROP(io_channels, "io-channel", "#io-channel-cells")
+DEFINE_SIMPLE_PROP(io_channels, "io-channels", "#io-channel-cells")
 DEFINE_SIMPLE_PROP(interrupt_parent, "interrupt-parent", NULL)
 DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells")
 DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells")
@@ -1262,7 +1234,6 @@ DEFINE_SIMPLE_PROP(pinctrl5, "pinctrl-5", NULL)
 DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL)
 DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
 DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
-DEFINE_SIMPLE_PROP(remote_endpoint, "remote-endpoint", NULL)
 DEFINE_SIMPLE_PROP(pwms, "pwms", "#pwm-cells")
 DEFINE_SIMPLE_PROP(resets, "resets", "#reset-cells")
 DEFINE_SIMPLE_PROP(leds, "leds", NULL)
@@ -1328,6 +1299,17 @@ static struct device_node *parse_interrupts(struct device_node *np,
        return of_irq_parse_one(np, index, &sup_args) ? NULL : sup_args.np;
 }
 
+static struct device_node *parse_remote_endpoint(struct device_node *np,
+                                                const char *prop_name,
+                                                int index)
+{
+       /* Return NULL for index > 0 to signify end of remote-endpoints. */
+       if (!index || strcmp(prop_name, "remote-endpoint"))
+               return NULL;
+
+       return of_graph_get_remote_port_parent(np);
+}
+
 static const struct supplier_bindings of_supplier_bindings[] = {
        { .parse_prop = parse_clocks, },
        { .parse_prop = parse_interconnects, },
@@ -1352,7 +1334,10 @@ static const struct supplier_bindings of_supplier_bindings[] = {
        { .parse_prop = parse_pinctrl6, },
        { .parse_prop = parse_pinctrl7, },
        { .parse_prop = parse_pinctrl8, },
-       { .parse_prop = parse_remote_endpoint, .node_not_dev = true, },
+       {
+               .parse_prop = parse_remote_endpoint,
+               .get_con_dev = of_graph_get_port_parent,
+       },
        { .parse_prop = parse_pwms, },
        { .parse_prop = parse_resets, },
        { .parse_prop = parse_leds, },
@@ -1403,8 +1388,8 @@ static int of_link_property(struct device_node *con_np, const char *prop_name)
                while ((phandle = s->parse_prop(con_np, prop_name, i))) {
                        struct device_node *con_dev_np;
 
-                       con_dev_np = s->node_not_dev
-                                       ? of_get_compat_node_parent(con_np)
+                       con_dev_np = s->get_con_dev
+                                       ? s->get_con_dev(con_np)
                                        : of_node_get(con_np);
                        matched = true;
                        i++;
index cfd60e35a8992d7d1bf7ee1ea42c10b6f43a7a2e..d7593bde2d02f39c2532ae4d0be41cccaec38526 100644 (file)
@@ -50,6 +50,12 @@ static struct unittest_results {
        failed; \
 })
 
+#ifdef CONFIG_OF_KOBJ
+#define OF_KREF_READ(NODE) kref_read(&(NODE)->kobj.kref)
+#else
+#define OF_KREF_READ(NODE) 1
+#endif
+
 /*
  * Expected message may have a message level other than KERN_INFO.
  * Print the expected message only if the current loglevel will allow
@@ -570,7 +576,7 @@ static void __init of_unittest_parse_phandle_with_args_map(void)
                        pr_err("missing testcase data\n");
                        return;
                }
-               prefs[i] = kref_read(&p[i]->kobj.kref);
+               prefs[i] = OF_KREF_READ(p[i]);
        }
 
        rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells");
@@ -693,9 +699,9 @@ static void __init of_unittest_parse_phandle_with_args_map(void)
        unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
 
        for (i = 0; i < ARRAY_SIZE(p); ++i) {
-               unittest(prefs[i] == kref_read(&p[i]->kobj.kref),
+               unittest(prefs[i] == OF_KREF_READ(p[i]),
                         "provider%d: expected:%d got:%d\n",
-                        i, prefs[i], kref_read(&p[i]->kobj.kref));
+                        i, prefs[i], OF_KREF_READ(p[i]));
                of_node_put(p[i]);
        }
 }
index 5befed2dc02b70bc5f4593b6e04a173e8e7ded08..9a437cfce073c16996927af40fa0e3816b7c7b32 100644 (file)
@@ -6,6 +6,7 @@
  * Author: Kishon Vijay Abraham I <kishon@ti.com>
  */
 
+#include <linux/align.h>
 #include <linux/bitfield.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -482,9 +483,10 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
                reg = ep_func->msi_cap + PCI_MSI_DATA_32;
                msg_data = dw_pcie_ep_readw_dbi(ep, func_no, reg);
        }
-       aligned_offset = msg_addr_lower & (epc->mem->window.page_size - 1);
-       msg_addr = ((u64)msg_addr_upper) << 32 |
-                       (msg_addr_lower & ~aligned_offset);
+       msg_addr = ((u64)msg_addr_upper) << 32 | msg_addr_lower;
+
+       aligned_offset = msg_addr & (epc->mem->window.page_size - 1);
+       msg_addr = ALIGN_DOWN(msg_addr, epc->mem->window.page_size);
        ret = dw_pcie_ep_map_addr(epc, func_no, 0, ep->msi_mem_phys, msg_addr,
                                  epc->mem->window.page_size);
        if (ret)
@@ -551,7 +553,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
        }
 
        aligned_offset = msg_addr & (epc->mem->window.page_size - 1);
-       msg_addr &= ~aligned_offset;
+       msg_addr = ALIGN_DOWN(msg_addr, epc->mem->window.page_size);
        ret = dw_pcie_ep_map_addr(epc, func_no, 0, ep->msi_mem_phys, msg_addr,
                                  epc->mem->window.page_size);
        if (ret)
index 9ab9b1008d8b9de897f1a1372f128e849b8a73a2..c3585229c12a2145401d675ff84c20288b8f158e 100644 (file)
@@ -2522,29 +2522,36 @@ static void pci_pme_list_scan(struct work_struct *work)
                if (pdev->pme_poll) {
                        struct pci_dev *bridge = pdev->bus->self;
                        struct device *dev = &pdev->dev;
-                       int pm_status;
+                       struct device *bdev = bridge ? &bridge->dev : NULL;
+                       int bref = 0;
 
                        /*
-                        * If bridge is in low power state, the
-                        * configuration space of subordinate devices
-                        * may be not accessible
+                        * If we have a bridge, it should be in an active/D0
+                        * state or the configuration space of subordinate
+                        * devices may not be accessible or stable over the
+                        * course of the call.
                         */
-                       if (bridge && bridge->current_state != PCI_D0)
-                               continue;
+                       if (bdev) {
+                               bref = pm_runtime_get_if_active(bdev, true);
+                               if (!bref)
+                                       continue;
+
+                               if (bridge->current_state != PCI_D0)
+                                       goto put_bridge;
+                       }
 
                        /*
-                        * If the device is in a low power state it
-                        * should not be polled either.
+                        * The device itself should be suspended but config
+                        * space must be accessible, therefore it cannot be in
+                        * D3cold.
                         */
-                       pm_status = pm_runtime_get_if_active(dev, true);
-                       if (!pm_status)
-                               continue;
-
-                       if (pdev->current_state != PCI_D3cold)
+                       if (pm_runtime_suspended(dev) &&
+                           pdev->current_state != PCI_D3cold)
                                pci_pme_wakeup(pdev, NULL);
 
-                       if (pm_status > 0)
-                               pm_runtime_put(dev);
+put_bridge:
+                       if (bref > 0)
+                               pm_runtime_put(bdev);
                } else {
                        list_del(&pme_dev->list);
                        kfree(pme_dev);
index c584165b13babd946eb7fcd84300bdf68abe31af..7e3aa7e2345fa3a9d7d3b1cb9c5dd40cc15498ff 100644 (file)
@@ -2305,6 +2305,17 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
                                dev_dbg(cmn->dev, "ignoring external node %llx\n", reg);
                                continue;
                        }
+                       /*
+                        * AmpereOneX erratum AC04_MESH_1 makes some XPs report a bogus
+                        * child count larger than the number of valid child pointers.
+                        * A child offset of 0 can only occur on CMN-600; otherwise it
+                        * would imply the root node being its own grandchild, which
+                        * we can safely dismiss in general.
+                        */
+                       if (reg == 0 && cmn->part != PART_CMN600) {
+                               dev_dbg(cmn->dev, "bogus child pointer?\n");
+                               continue;
+                       }
 
                        arm_cmn_init_node_info(cmn, reg & CMN_CHILD_NODE_ADDR, dn);
 
index 365d964b0f6a6d7382455f3b07035fafe1de1fa2..bc0d414a6aff94ee8980821666eb0c18bca4954f 100644 (file)
@@ -419,7 +419,7 @@ static struct attribute *cxl_pmu_event_attrs[] = {
        CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmp,                     CXL_PMU_GID_S2M_NDR, BIT(0)),
        CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmps,                    CXL_PMU_GID_S2M_NDR, BIT(1)),
        CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmpe,                    CXL_PMU_GID_S2M_NDR, BIT(2)),
-       CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_biconflictack,           CXL_PMU_GID_S2M_NDR, BIT(3)),
+       CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_biconflictack,           CXL_PMU_GID_S2M_NDR, BIT(4)),
        /* CXL rev 3.0 Table 3-46 S2M DRS opcodes */
        CXL_PMU_EVENT_CXL_ATTR(s2m_drs_memdata,                 CXL_PMU_GID_S2M_DRS, BIT(0)),
        CXL_PMU_EVENT_CXL_ATTR(s2m_drs_memdatanxm,              CXL_PMU_GID_S2M_DRS, BIT(1)),
index 03ecb3d1aaf60da974f32bb344203b418969064f..49f89b70dcecb4a4465b62aecded05aa3e0b19f7 100644 (file)
@@ -1159,7 +1159,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
        }
 
        ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler,
-                              IRQF_SHARED, KBUILD_MODNAME, gpio_dev);
+                              IRQF_SHARED | IRQF_ONESHOT, KBUILD_MODNAME, gpio_dev);
        if (ret)
                goto out2;
 
index a1f6cba3ae6c86a386ab68bf46866ee95663eb51..18e232b5ed53d73ab24bd4fe3dab94c69235436d 100644 (file)
@@ -1109,7 +1109,7 @@ static int __init genpd_power_off_unused(void)
 
        return 0;
 }
-late_initcall(genpd_power_off_unused);
+late_initcall_sync(genpd_power_off_unused);
 
 #ifdef CONFIG_PM_SLEEP
 
index e26dc17d07ad71d8398044670227c93a6bdd4427..e274e3315fe7a60887bec6a1fa85db69156e7fd6 100644 (file)
@@ -561,6 +561,11 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren
                        goto err_put_node;
                }
 
+               /* recursive call to add all subdomains */
+               ret = scpsys_add_subdomain(scpsys, child);
+               if (ret)
+                       goto err_put_node;
+
                ret = pm_genpd_add_subdomain(parent_pd, child_pd);
                if (ret) {
                        dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n",
@@ -570,11 +575,6 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren
                        dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name,
                                child_pd->name);
                }
-
-               /* recursive call to add all subdomains */
-               ret = scpsys_add_subdomain(scpsys, child);
-               if (ret)
-                       goto err_put_node;
        }
 
        return 0;
@@ -588,9 +588,6 @@ static void scpsys_remove_one_domain(struct scpsys_domain *pd)
 {
        int ret;
 
-       if (scpsys_domain_is_on(pd))
-               scpsys_power_off(&pd->genpd);
-
        /*
         * We're in the error cleanup already, so we only complain,
         * but won't emit another error on top of the original one.
@@ -600,6 +597,8 @@ static void scpsys_remove_one_domain(struct scpsys_domain *pd)
                dev_err(pd->scpsys->dev,
                        "failed to remove domain '%s' : %d - state may be inconsistent\n",
                        pd->genpd.name, ret);
+       if (scpsys_domain_is_on(pd))
+               scpsys_power_off(&pd->genpd);
 
        clk_bulk_put(pd->num_clks, pd->clks);
        clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
index 39ca84a67daadd21202e1ba80f13ec6cbc671a7a..621e411fc9991a4050cd6da699695912f18a46b0 100644 (file)
@@ -25,7 +25,8 @@ static const struct rcar_sysc_area r8a77980_areas[] __initconst = {
          PD_CPU_NOCR },
        { "ca53-cpu3",  0x200, 3, R8A77980_PD_CA53_CPU3, R8A77980_PD_CA53_SCU,
          PD_CPU_NOCR },
-       { "cr7",        0x240, 0, R8A77980_PD_CR7,      R8A77980_PD_ALWAYS_ON },
+       { "cr7",        0x240, 0, R8A77980_PD_CR7,      R8A77980_PD_ALWAYS_ON,
+         PD_CPU_NOCR },
        { "a3ir",       0x180, 0, R8A77980_PD_A3IR,     R8A77980_PD_ALWAYS_ON },
        { "a2ir0",      0x400, 0, R8A77980_PD_A2IR0,    R8A77980_PD_A3IR },
        { "a2ir1",      0x400, 1, R8A77980_PD_A2IR1,    R8A77980_PD_A3IR },
index b92a32b4b1141670cc2f3c2e8b91a8e1d526b26a..04c64ce0a1ca1a2006d31ca5c7ee819598f155c4 100644 (file)
@@ -255,9 +255,10 @@ static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover)
                if (!recover) {
                        hash_del(&addr->hnode);
                        kfree(addr);
-                       continue;
+               } else {
+                       /* prepare for recovery */
+                       addr->disp_flag = QETH_DISP_ADDR_ADD;
                }
-               addr->disp_flag = QETH_DISP_ADDR_ADD;
        }
 
        mutex_unlock(&card->ip_lock);
@@ -278,9 +279,11 @@ static void qeth_l3_recover_ip(struct qeth_card *card)
                if (addr->disp_flag == QETH_DISP_ADDR_ADD) {
                        rc = qeth_l3_register_addr_entry(card, addr);
 
-                       if (!rc) {
+                       if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) {
+                               /* keep it in the records */
                                addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
                        } else {
+                               /* bad address */
                                hash_del(&addr->hnode);
                                kfree(addr);
                        }
index 19eee108db02145e55d6bebc33a03e4fffba1ef5..5c8d1ba3f8f3c9c2de41e7f111db57f2b4c3e63a 100644 (file)
@@ -319,17 +319,16 @@ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
 {
        struct fcoe_fcf *sel;
        struct fcoe_fcf *fcf;
-       unsigned long flags;
 
        mutex_lock(&fip->ctlr_mutex);
-       spin_lock_irqsave(&fip->ctlr_lock, flags);
+       spin_lock_bh(&fip->ctlr_lock);
 
        kfree_skb(fip->flogi_req);
        fip->flogi_req = NULL;
        list_for_each_entry(fcf, &fip->fcfs, list)
                fcf->flogi_sent = 0;
 
-       spin_unlock_irqrestore(&fip->ctlr_lock, flags);
+       spin_unlock_bh(&fip->ctlr_lock);
        sel = fip->sel_fcf;
 
        if (sel && ether_addr_equal(sel->fcf_mac, fip->dest_addr))
@@ -700,7 +699,6 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
 {
        struct fc_frame *fp;
        struct fc_frame_header *fh;
-       unsigned long flags;
        u16 old_xid;
        u8 op;
        u8 mac[ETH_ALEN];
@@ -734,11 +732,11 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
                op = FIP_DT_FLOGI;
                if (fip->mode == FIP_MODE_VN2VN)
                        break;
-               spin_lock_irqsave(&fip->ctlr_lock, flags);
+               spin_lock_bh(&fip->ctlr_lock);
                kfree_skb(fip->flogi_req);
                fip->flogi_req = skb;
                fip->flogi_req_send = 1;
-               spin_unlock_irqrestore(&fip->ctlr_lock, flags);
+               spin_unlock_bh(&fip->ctlr_lock);
                schedule_work(&fip->timer_work);
                return -EINPROGRESS;
        case ELS_FDISC:
@@ -1707,11 +1705,10 @@ static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
 static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
 {
        struct fcoe_fcf *fcf;
-       unsigned long flags;
        int error;
 
        mutex_lock(&fip->ctlr_mutex);
-       spin_lock_irqsave(&fip->ctlr_lock, flags);
+       spin_lock_bh(&fip->ctlr_lock);
        LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
        fcf = fcoe_ctlr_select(fip);
        if (!fcf || fcf->flogi_sent) {
@@ -1722,7 +1719,7 @@ static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
                fcoe_ctlr_solicit(fip, NULL);
                error = fcoe_ctlr_flogi_send_locked(fip);
        }
-       spin_unlock_irqrestore(&fip->ctlr_lock, flags);
+       spin_unlock_bh(&fip->ctlr_lock);
        mutex_unlock(&fip->ctlr_mutex);
        return error;
 }
@@ -1739,9 +1736,8 @@ static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
 static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
 {
        struct fcoe_fcf *fcf;
-       unsigned long flags;
 
-       spin_lock_irqsave(&fip->ctlr_lock, flags);
+       spin_lock_bh(&fip->ctlr_lock);
        fcf = fip->sel_fcf;
        if (!fcf || !fip->flogi_req_send)
                goto unlock;
@@ -1768,7 +1764,7 @@ static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
        } else /* XXX */
                LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
 unlock:
-       spin_unlock_irqrestore(&fip->ctlr_lock, flags);
+       spin_unlock_bh(&fip->ctlr_lock);
 }
 
 /**
index 2074937c05bc855dea5a580079b84fd677460fb5..ce73f08ee889f1409c43583d959baeae6f0fb895 100644 (file)
@@ -305,6 +305,7 @@ struct fnic {
        unsigned int copy_wq_base;
        struct work_struct link_work;
        struct work_struct frame_work;
+       struct work_struct flush_work;
        struct sk_buff_head frame_queue;
        struct sk_buff_head tx_queue;
 
@@ -363,7 +364,7 @@ void fnic_handle_event(struct work_struct *work);
 int fnic_rq_cmpl_handler(struct fnic *fnic, int);
 int fnic_alloc_rq_frame(struct vnic_rq *rq);
 void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf);
-void fnic_flush_tx(struct fnic *);
+void fnic_flush_tx(struct work_struct *work);
 void fnic_eth_send(struct fcoe_ctlr *, struct sk_buff *skb);
 void fnic_set_port_id(struct fc_lport *, u32, struct fc_frame *);
 void fnic_update_mac(struct fc_lport *, u8 *new);
index 5e312a55cc7da0c73811b0fc26aed17d8c6a034c..a08293b2ad9f59031d5220aba3480a84461a0e8a 100644 (file)
@@ -1182,7 +1182,7 @@ int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
 
 /**
  * fnic_flush_tx() - send queued frames.
- * @fnic: fnic device
+ * @work: pointer to work element
  *
  * Send frames that were waiting to go out in FC or Ethernet mode.
  * Whenever changing modes we purge queued frames, so these frames should
@@ -1190,8 +1190,9 @@ int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
  *
  * Called without fnic_lock held.
  */
-void fnic_flush_tx(struct fnic *fnic)
+void fnic_flush_tx(struct work_struct *work)
 {
+       struct fnic *fnic = container_of(work, struct fnic, flush_work);
        struct sk_buff *skb;
        struct fc_frame *fp;
 
index 5ed1d897311a88c0d1194bff7b36e9677a45166f..29eead383eb9a478bb71643eaac1a4e302418f0f 100644 (file)
@@ -830,6 +830,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                spin_lock_init(&fnic->vlans_lock);
                INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame);
                INIT_WORK(&fnic->event_work, fnic_handle_event);
+               INIT_WORK(&fnic->flush_work, fnic_flush_tx);
                skb_queue_head_init(&fnic->fip_frame_queue);
                INIT_LIST_HEAD(&fnic->evlist);
                INIT_LIST_HEAD(&fnic->vlans);
index 8d7fc5284293b5283523b049ba38387857ebb09e..fc4cee91b175c14d0950337ac8928b659cbc8cef 100644 (file)
@@ -680,7 +680,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
 
        spin_unlock_irqrestore(&fnic->fnic_lock, flags);
 
-       fnic_flush_tx(fnic);
+       queue_work(fnic_event_queue, &fnic->flush_work);
 
  reset_cmpl_handler_end:
        fnic_clear_state_flags(fnic, FNIC_FLAGS_FWRESET);
@@ -736,7 +736,7 @@ static int fnic_fcpio_flogi_reg_cmpl_handler(struct fnic *fnic,
                }
                spin_unlock_irqrestore(&fnic->fnic_lock, flags);
 
-               fnic_flush_tx(fnic);
+               queue_work(fnic_event_queue, &fnic->flush_work);
                queue_work(fnic_event_queue, &fnic->frame_work);
        } else {
                spin_unlock_irqrestore(&fnic->fnic_lock, flags);
index d26941b131fdb81e6bc9fe48ccc57b75a0055af5..bf879d81846b69379f34b91759a45ef8d5af89fb 100644 (file)
@@ -1918,7 +1918,7 @@ out:
  *
  * Returns the number of SGEs added to the SGL.
  **/
-static int
+static uint32_t
 lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                struct sli4_sge *sgl, int datasegcnt,
                struct lpfc_io_buf *lpfc_cmd)
@@ -1926,8 +1926,8 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        struct scatterlist *sgde = NULL; /* s/g data entry */
        struct sli4_sge_diseed *diseed = NULL;
        dma_addr_t physaddr;
-       int i = 0, num_sge = 0, status;
-       uint32_t reftag;
+       int i = 0, status;
+       uint32_t reftag, num_sge = 0;
        uint8_t txop, rxop;
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        uint32_t rc;
@@ -2099,7 +2099,7 @@ out:
  *
  * Returns the number of SGEs added to the SGL.
  **/
-static int
+static uint32_t
 lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                struct sli4_sge *sgl, int datacnt, int protcnt,
                struct lpfc_io_buf *lpfc_cmd)
@@ -2123,8 +2123,8 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        uint32_t rc;
 #endif
        uint32_t checking = 1;
-       uint32_t dma_offset = 0;
-       int num_sge = 0, j = 2;
+       uint32_t dma_offset = 0, num_sge = 0;
+       int j = 2;
        struct sli4_hybrid_sgl *sgl_xtra = NULL;
 
        sgpe = scsi_prot_sglist(sc);
index 4f455884fdc440188124d845ef0535f4da418d22..612489afe8d2467965759c80562562e26919f704 100644 (file)
@@ -282,11 +282,12 @@ static void scsi_eh_inc_host_failed(struct rcu_head *head)
 {
        struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu);
        struct Scsi_Host *shost = scmd->device->host;
+       unsigned int busy = scsi_host_busy(shost);
        unsigned long flags;
 
        spin_lock_irqsave(shost->host_lock, flags);
        shost->host_failed++;
-       scsi_eh_wakeup(shost, scsi_host_busy(shost));
+       scsi_eh_wakeup(shost, busy);
        spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
index 1fb80eae9a63a30787dee6583e2a0cfe5c96f0ce..df5ac03d5d6c2eb5233ad7fcfdad37a1e487b4e6 100644 (file)
@@ -278,9 +278,11 @@ static void scsi_dec_host_busy(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
        rcu_read_lock();
        __clear_bit(SCMD_STATE_INFLIGHT, &cmd->state);
        if (unlikely(scsi_host_in_recovery(shost))) {
+               unsigned int busy = scsi_host_busy(shost);
+
                spin_lock_irqsave(shost->host_lock, flags);
                if (shost->host_failed || shost->host_eh_scheduled)
-                       scsi_eh_wakeup(shost, scsi_host_busy(shost));
+                       scsi_eh_wakeup(shost, busy);
                spin_unlock_irqrestore(shost->host_lock, flags);
        }
        rcu_read_unlock();
index 546cdce525fc5b1b49b305b872e81d2b0aed0cb5..833a1bb7a91438e02c2d5a176e1afdaba4159552 100644 (file)
@@ -2,6 +2,7 @@
 // Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
 // Copyright (C) 2008 Juergen Beisert
 
+#include <linux/bits.h>
 #include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
@@ -660,15 +661,15 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
                        << MX51_ECSPI_CTRL_BL_OFFSET;
        else {
                if (spi_imx->usedma) {
-                       ctrl |= (spi_imx->bits_per_word *
-                               spi_imx_bytes_per_word(spi_imx->bits_per_word) - 1)
+                       ctrl |= (spi_imx->bits_per_word - 1)
                                << MX51_ECSPI_CTRL_BL_OFFSET;
                } else {
                        if (spi_imx->count >= MX51_ECSPI_CTRL_MAX_BURST)
-                               ctrl |= (MX51_ECSPI_CTRL_MAX_BURST - 1)
+                               ctrl |= (MX51_ECSPI_CTRL_MAX_BURST * BITS_PER_BYTE - 1)
                                                << MX51_ECSPI_CTRL_BL_OFFSET;
                        else
-                               ctrl |= (spi_imx->count * spi_imx->bits_per_word - 1)
+                               ctrl |= spi_imx->count / DIV_ROUND_UP(spi_imx->bits_per_word,
+                                               BITS_PER_BYTE) * spi_imx->bits_per_word
                                                << MX51_ECSPI_CTRL_BL_OFFSET;
                }
        }
index 07d20ca1164c357813e075b7a1a6763da735ab0a..4337ca51d7aa21555684f62295a39a52772cce3d 100644 (file)
@@ -85,6 +85,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = {
        { PCI_VDEVICE(INTEL, 0xa2a4), (unsigned long)&cnl_info },
        { PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info },
        { PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&cnl_info },
+       { PCI_VDEVICE(INTEL, 0xa823), (unsigned long)&cnl_info },
        { },
 };
 MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids);
index 1bf080339b5a722b8ec6abb356f8bad231d19d9f..88cbe4f00cc3b11e5fef822a60114a90a88149f8 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/mxs-spi.h>
 #include <trace/events/spi.h>
+#include <linux/dma/mxs-dma.h>
 
 #define DRIVER_NAME            "mxs-spi"
 
@@ -252,7 +253,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi,
                desc = dmaengine_prep_slave_sg(ssp->dmach,
                                &dma_xfer[sg_count].sg, 1,
                                (flags & TXRX_WRITE) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
-                               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+                               DMA_PREP_INTERRUPT | MXS_DMA_CTRL_WAIT4END);
 
                if (!desc) {
                        dev_err(ssp->dev,
index a0c9fea908f553e0bf007a7a78a35746f60a25f4..ddf1c684bcc7d863ede340aa196506a3a3505654 100644 (file)
@@ -53,8 +53,6 @@
 
 /* per-register bitmasks: */
 #define OMAP2_MCSPI_IRQSTATUS_EOW      BIT(17)
-#define OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY    BIT(0)
-#define OMAP2_MCSPI_IRQSTATUS_RX0_FULL    BIT(2)
 
 #define OMAP2_MCSPI_MODULCTRL_SINGLE   BIT(0)
 #define OMAP2_MCSPI_MODULCTRL_MS       BIT(2)
@@ -293,7 +291,7 @@ static void omap2_mcspi_set_mode(struct spi_controller *ctlr)
 }
 
 static void omap2_mcspi_set_fifo(const struct spi_device *spi,
-                               struct spi_transfer *t, int enable, int dma_enabled)
+                               struct spi_transfer *t, int enable)
 {
        struct spi_controller *ctlr = spi->controller;
        struct omap2_mcspi_cs *cs = spi->controller_state;
@@ -314,28 +312,20 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi,
                        max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH / 2;
                else
                        max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH;
-               if (dma_enabled)
-                       wcnt = t->len / bytes_per_word;
-               else
-                       wcnt = 0;
+
+               wcnt = t->len / bytes_per_word;
                if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT)
                        goto disable_fifo;
 
                xferlevel = wcnt << 16;
                if (t->rx_buf != NULL) {
                        chconf |= OMAP2_MCSPI_CHCONF_FFER;
-                       if (dma_enabled)
-                               xferlevel |= (bytes_per_word - 1) << 8;
-                       else
-                               xferlevel |= (max_fifo_depth - 1) << 8;
+                       xferlevel |= (bytes_per_word - 1) << 8;
                }
 
                if (t->tx_buf != NULL) {
                        chconf |= OMAP2_MCSPI_CHCONF_FFET;
-                       if (dma_enabled)
-                               xferlevel |= bytes_per_word - 1;
-                       else
-                               xferlevel |= (max_fifo_depth - 1);
+                       xferlevel |= bytes_per_word - 1;
                }
 
                mcspi_write_reg(ctlr, OMAP2_MCSPI_XFERLEVEL, xferlevel);
@@ -892,113 +882,6 @@ out:
        return count - c;
 }
 
-static unsigned
-omap2_mcspi_txrx_piofifo(struct spi_device *spi, struct spi_transfer *xfer)
-{
-       struct omap2_mcspi_cs   *cs = spi->controller_state;
-       struct omap2_mcspi    *mcspi;
-       unsigned int            count, c;
-       unsigned int            iter, cwc;
-       int last_request;
-       void __iomem            *base = cs->base;
-       void __iomem            *tx_reg;
-       void __iomem            *rx_reg;
-       void __iomem            *chstat_reg;
-       void __iomem        *irqstat_reg;
-       int                     word_len, bytes_per_word;
-       u8              *rx;
-       const u8        *tx;
-
-       mcspi = spi_controller_get_devdata(spi->controller);
-       count = xfer->len;
-       c = count;
-       word_len = cs->word_len;
-       bytes_per_word = mcspi_bytes_per_word(word_len);
-
-       /*
-        * We store the pre-calculated register addresses on stack to speed
-        * up the transfer loop.
-        */
-       tx_reg          = base + OMAP2_MCSPI_TX0;
-       rx_reg          = base + OMAP2_MCSPI_RX0;
-       chstat_reg      = base + OMAP2_MCSPI_CHSTAT0;
-       irqstat_reg    = base + OMAP2_MCSPI_IRQSTATUS;
-
-       if (c < (word_len >> 3))
-               return 0;
-
-       rx = xfer->rx_buf;
-       tx = xfer->tx_buf;
-
-       do {
-               /* calculate number of words in current iteration */
-               cwc = min((unsigned int)mcspi->fifo_depth / bytes_per_word,
-                         c / bytes_per_word);
-               last_request = cwc != (mcspi->fifo_depth / bytes_per_word);
-               if (tx) {
-                       if (mcspi_wait_for_reg_bit(irqstat_reg,
-                                                  OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY) < 0) {
-                               dev_err(&spi->dev, "TX Empty timed out\n");
-                               goto out;
-                       }
-                       writel_relaxed(OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY, irqstat_reg);
-
-                       for (iter = 0; iter < cwc; iter++, tx += bytes_per_word) {
-                               if (bytes_per_word == 1)
-                                       writel_relaxed(*tx, tx_reg);
-                               else if (bytes_per_word == 2)
-                                       writel_relaxed(*((u16 *)tx), tx_reg);
-                               else if (bytes_per_word == 4)
-                                       writel_relaxed(*((u32 *)tx), tx_reg);
-                       }
-               }
-
-               if (rx) {
-                       if (!last_request &&
-                           mcspi_wait_for_reg_bit(irqstat_reg,
-                                                  OMAP2_MCSPI_IRQSTATUS_RX0_FULL) < 0) {
-                               dev_err(&spi->dev, "RX_FULL timed out\n");
-                               goto out;
-                       }
-                       writel_relaxed(OMAP2_MCSPI_IRQSTATUS_RX0_FULL, irqstat_reg);
-
-                       for (iter = 0; iter < cwc; iter++, rx += bytes_per_word) {
-                               if (last_request &&
-                                   mcspi_wait_for_reg_bit(chstat_reg,
-                                                          OMAP2_MCSPI_CHSTAT_RXS) < 0) {
-                                       dev_err(&spi->dev, "RXS timed out\n");
-                                       goto out;
-                               }
-                               if (bytes_per_word == 1)
-                                       *rx = readl_relaxed(rx_reg);
-                               else if (bytes_per_word == 2)
-                                       *((u16 *)rx) = readl_relaxed(rx_reg);
-                               else if (bytes_per_word == 4)
-                                       *((u32 *)rx) = readl_relaxed(rx_reg);
-                       }
-               }
-
-               if (last_request) {
-                       if (mcspi_wait_for_reg_bit(chstat_reg,
-                                                  OMAP2_MCSPI_CHSTAT_EOT) < 0) {
-                               dev_err(&spi->dev, "EOT timed out\n");
-                               goto out;
-                       }
-                       if (mcspi_wait_for_reg_bit(chstat_reg,
-                                                  OMAP2_MCSPI_CHSTAT_TXFFE) < 0) {
-                               dev_err(&spi->dev, "TXFFE timed out\n");
-                               goto out;
-                       }
-                       omap2_mcspi_set_enable(spi, 0);
-               }
-               c -= cwc * bytes_per_word;
-       } while (c >= bytes_per_word);
-
-out:
-       omap2_mcspi_set_enable(spi, 1);
-       return count - c;
-}
-
 static u32 omap2_mcspi_calc_divisor(u32 speed_hz, u32 ref_clk_hz)
 {
        u32 div;
@@ -1323,9 +1206,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
                if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
                    ctlr->cur_msg_mapped &&
                    ctlr->can_dma(ctlr, spi, t))
-                       omap2_mcspi_set_fifo(spi, t, 1, 1);
-               else if (t->len > OMAP2_MCSPI_MAX_FIFODEPTH)
-                       omap2_mcspi_set_fifo(spi, t, 1, 0);
+                       omap2_mcspi_set_fifo(spi, t, 1);
 
                omap2_mcspi_set_enable(spi, 1);
 
@@ -1338,8 +1219,6 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
                    ctlr->cur_msg_mapped &&
                    ctlr->can_dma(ctlr, spi, t))
                        count = omap2_mcspi_txrx_dma(spi, t);
-               else if (mcspi->fifo_depth > 0)
-                       count = omap2_mcspi_txrx_piofifo(spi, t);
                else
                        count = omap2_mcspi_txrx_pio(spi, t);
 
@@ -1352,7 +1231,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
        omap2_mcspi_set_enable(spi, 0);
 
        if (mcspi->fifo_depth > 0)
-               omap2_mcspi_set_fifo(spi, t, 0, 0);
+               omap2_mcspi_set_fifo(spi, t, 0);
 
 out:
        /* Restore defaults if they were overriden */
@@ -1375,7 +1254,7 @@ out:
                omap2_mcspi_set_cs(spi, !(spi->mode & SPI_CS_HIGH));
 
        if (mcspi->fifo_depth > 0 && t)
-               omap2_mcspi_set_fifo(spi, t, 0, 0);
+               omap2_mcspi_set_fifo(spi, t, 0);
 
        return status;
 }
index 03aab661be9d33af1ff6ad93052171f206402b83..942c3117ab3a904de67c59e7e13e5d40995dd00a 100644 (file)
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
+#include <linux/platform_device.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
@@ -166,10 +168,8 @@ static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
        int scr;
        u8 cdm = 0;
        u32 speed;
-       u8 bits_per_word;
 
        /* Start with the generic configuration for this device. */
-       bits_per_word = spi->bits_per_word;
        speed = spi->max_speed_hz;
 
        /*
@@ -177,9 +177,6 @@ static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
         * the transfer to overwrite the generic configuration with zeros.
         */
        if (t) {
-               if (t->bits_per_word)
-                       bits_per_word = t->bits_per_word;
-
                if (t->speed_hz)
                        speed = min(t->speed_hz, spi->max_speed_hz);
        }
@@ -362,22 +359,22 @@ static int spi_ppc4xx_of_probe(struct platform_device *op)
 
        /* Setup the state for the bitbang driver */
        bbp = &hw->bitbang;
-       bbp->master = hw->host;
+       bbp->ctlr = hw->host;
        bbp->setup_transfer = spi_ppc4xx_setupxfer;
        bbp->txrx_bufs = spi_ppc4xx_txrx;
        bbp->use_dma = 0;
-       bbp->master->setup = spi_ppc4xx_setup;
-       bbp->master->cleanup = spi_ppc4xx_cleanup;
-       bbp->master->bits_per_word_mask = SPI_BPW_MASK(8);
-       bbp->master->use_gpio_descriptors = true;
+       bbp->ctlr->setup = spi_ppc4xx_setup;
+       bbp->ctlr->cleanup = spi_ppc4xx_cleanup;
+       bbp->ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
+       bbp->ctlr->use_gpio_descriptors = true;
        /*
         * The SPI core will count the number of GPIO descriptors to figure
         * out the number of chip selects available on the platform.
         */
-       bbp->master->num_chipselect = 0;
+       bbp->ctlr->num_chipselect = 0;
 
        /* the spi->mode bits understood by this driver: */
-       bbp->master->mode_bits =
+       bbp->ctlr->mode_bits =
                SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST;
 
        /* Get the clock for the OPB */
index f44e6412f4e31a4ee3ab22cc650eee5a49ee31a1..d0db2efe004525e9d88531e0115c8edd2fa9c4df 100644 (file)
@@ -3723,12 +3723,10 @@ apply_min_padding:
 
 static int atomisp_set_crop(struct atomisp_device *isp,
                            const struct v4l2_mbus_framefmt *format,
+                           struct v4l2_subdev_state *sd_state,
                            int which)
 {
        struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr];
-       struct v4l2_subdev_state pad_state = {
-               .pads = &input->pad_cfg,
-       };
        struct v4l2_subdev_selection sel = {
                .which = which,
                .target = V4L2_SEL_TGT_CROP,
@@ -3754,7 +3752,7 @@ static int atomisp_set_crop(struct atomisp_device *isp,
        sel.r.left = ((input->native_rect.width - sel.r.width) / 2) & ~1;
        sel.r.top = ((input->native_rect.height - sel.r.height) / 2) & ~1;
 
-       ret = v4l2_subdev_call(input->camera, pad, set_selection, &pad_state, &sel);
+       ret = v4l2_subdev_call(input->camera, pad, set_selection, sd_state, &sel);
        if (ret)
                dev_err(isp->dev, "Error setting crop to %ux%u @%ux%u: %d\n",
                        sel.r.width, sel.r.height, sel.r.left, sel.r.top, ret);
@@ -3770,9 +3768,6 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
        const struct atomisp_format_bridge *fmt, *snr_fmt;
        struct atomisp_sub_device *asd = &isp->asd;
        struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
-       struct v4l2_subdev_state pad_state = {
-               .pads = &input->pad_cfg,
-       };
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
@@ -3809,11 +3804,16 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
        dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n",
                format.format.width, format.format.height);
 
-       ret = atomisp_set_crop(isp, &format.format, V4L2_SUBDEV_FORMAT_TRY);
-       if (ret)
-               return ret;
+       v4l2_subdev_lock_state(input->try_sd_state);
+
+       ret = atomisp_set_crop(isp, &format.format, input->try_sd_state,
+                              V4L2_SUBDEV_FORMAT_TRY);
+       if (ret == 0)
+               ret = v4l2_subdev_call(input->camera, pad, set_fmt,
+                                      input->try_sd_state, &format);
+
+       v4l2_subdev_unlock_state(input->try_sd_state);
 
-       ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &format);
        if (ret)
                return ret;
 
@@ -4238,9 +4238,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
        struct atomisp_device *isp = asd->isp;
        struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
        const struct atomisp_format_bridge *format;
-       struct v4l2_subdev_state pad_state = {
-               .pads = &input->pad_cfg,
-       };
+       struct v4l2_subdev_state *act_sd_state;
        struct v4l2_subdev_format vformat = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
@@ -4268,12 +4266,18 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
 
        /* Disable dvs if resolution can't be supported by sensor */
        if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
-               ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_TRY);
-               if (ret)
-                       return ret;
+               v4l2_subdev_lock_state(input->try_sd_state);
+
+               ret = atomisp_set_crop(isp, &vformat.format, input->try_sd_state,
+                                      V4L2_SUBDEV_FORMAT_TRY);
+               if (ret == 0) {
+                       vformat.which = V4L2_SUBDEV_FORMAT_TRY;
+                       ret = v4l2_subdev_call(input->camera, pad, set_fmt,
+                                              input->try_sd_state, &vformat);
+               }
+
+               v4l2_subdev_unlock_state(input->try_sd_state);
 
-               vformat.which = V4L2_SUBDEV_FORMAT_TRY;
-               ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &vformat);
                if (ret)
                        return ret;
 
@@ -4291,12 +4295,18 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
                }
        }
 
-       ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_ACTIVE);
-       if (ret)
-               return ret;
+       act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
+
+       ret = atomisp_set_crop(isp, &vformat.format, act_sd_state,
+                              V4L2_SUBDEV_FORMAT_ACTIVE);
+       if (ret == 0) {
+               vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+               ret = v4l2_subdev_call(input->camera, pad, set_fmt, act_sd_state, &vformat);
+       }
+
+       if (act_sd_state)
+               v4l2_subdev_unlock_state(act_sd_state);
 
-       vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-       ret = v4l2_subdev_call(input->camera, pad, set_fmt, NULL, &vformat);
        if (ret)
                return ret;
 
index f7b4bee9574bdb8ea330bec4e04074515e71f5a5..d5b077e602caec6ac2863780f660f7aac751ff02 100644 (file)
@@ -132,8 +132,8 @@ struct atomisp_input_subdev {
        /* Sensor rects for sensors which support crop */
        struct v4l2_rect native_rect;
        struct v4l2_rect active_rect;
-       /* Sensor pad_cfg for which == V4L2_SUBDEV_FORMAT_TRY calls */
-       struct v4l2_subdev_pad_config pad_cfg;
+       /* Sensor state for which == V4L2_SUBDEV_FORMAT_TRY calls */
+       struct v4l2_subdev_state *try_sd_state;
 
        struct v4l2_subdev *motor;
 
index 01b7fa9b56a21378459f3aa4101eab6195558546..5b2d88c02d36a083376ee21660923635e9ff70c4 100644 (file)
@@ -781,12 +781,20 @@ static int atomisp_enum_framesizes(struct file *file, void *priv,
                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
                .code = input->code,
        };
+       struct v4l2_subdev_state *act_sd_state;
        int ret;
 
+       if (!input->camera)
+               return -EINVAL;
+
        if (input->crop_support)
                return atomisp_enum_framesizes_crop(isp, fsize);
 
-       ret = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse);
+       act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
+       ret = v4l2_subdev_call(input->camera, pad, enum_frame_size,
+                              act_sd_state, &fse);
+       if (act_sd_state)
+               v4l2_subdev_unlock_state(act_sd_state);
        if (ret)
                return ret;
 
@@ -803,18 +811,25 @@ static int atomisp_enum_frameintervals(struct file *file, void *priv,
        struct video_device *vdev = video_devdata(file);
        struct atomisp_device *isp = video_get_drvdata(vdev);
        struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
+       struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
        struct v4l2_subdev_frame_interval_enum fie = {
-               .code   = atomisp_in_fmt_conv[0].code,
+               .code = atomisp_in_fmt_conv[0].code,
                .index = fival->index,
                .width = fival->width,
                .height = fival->height,
                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
        };
+       struct v4l2_subdev_state *act_sd_state;
        int ret;
 
-       ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
-                              pad, enum_frame_interval, NULL,
-                              &fie);
+       if (!input->camera)
+               return -EINVAL;
+
+       act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
+       ret = v4l2_subdev_call(input->camera, pad, enum_frame_interval,
+                              act_sd_state, &fie);
+       if (act_sd_state)
+               v4l2_subdev_unlock_state(act_sd_state);
        if (ret)
                return ret;
 
@@ -830,30 +845,25 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh,
        struct video_device *vdev = video_devdata(file);
        struct atomisp_device *isp = video_get_drvdata(vdev);
        struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
+       struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
        struct v4l2_subdev_mbus_code_enum code = {
                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
        };
        const struct atomisp_format_bridge *format;
-       struct v4l2_subdev *camera;
+       struct v4l2_subdev_state *act_sd_state;
        unsigned int i, fi = 0;
-       int rval;
+       int ret;
 
-       camera = isp->inputs[asd->input_curr].camera;
-       if(!camera) {
-               dev_err(isp->dev, "%s(): camera is NULL, device is %s\n",
-                       __func__, vdev->name);
+       if (!input->camera)
                return -EINVAL;
-       }
 
-       rval = v4l2_subdev_call(camera, pad, enum_mbus_code, NULL, &code);
-       if (rval == -ENOIOCTLCMD) {
-               dev_warn(isp->dev,
-                        "enum_mbus_code pad op not supported by %s. Please fix your sensor driver!\n",
-                        camera->name);
-       }
-
-       if (rval)
-               return rval;
+       act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
+       ret = v4l2_subdev_call(input->camera, pad, enum_mbus_code,
+                              act_sd_state, &code);
+       if (act_sd_state)
+               v4l2_subdev_unlock_state(act_sd_state);
+       if (ret)
+               return ret;
 
        for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) {
                format = &atomisp_output_fmts[i];
index c1c8501ec61f57046af5027c8f9a4170597210d5..547e1444ad9733569816c1e43c74e542089f82fa 100644 (file)
@@ -862,6 +862,9 @@ static void atomisp_unregister_entities(struct atomisp_device *isp)
        v4l2_device_unregister(&isp->v4l2_dev);
        media_device_unregister(&isp->media_dev);
        media_device_cleanup(&isp->media_dev);
+
+       for (i = 0; i < isp->input_cnt; i++)
+               __v4l2_subdev_state_free(isp->inputs[i].try_sd_state);
 }
 
 static int atomisp_register_entities(struct atomisp_device *isp)
@@ -933,32 +936,49 @@ v4l2_device_failed:
 
 static void atomisp_init_sensor(struct atomisp_input_subdev *input)
 {
+       static struct lock_class_key try_sd_state_key;
        struct v4l2_subdev_mbus_code_enum mbus_code_enum = { };
        struct v4l2_subdev_frame_size_enum fse = { };
-       struct v4l2_subdev_state sd_state = {
-               .pads = &input->pad_cfg,
-       };
        struct v4l2_subdev_selection sel = { };
+       struct v4l2_subdev_state *try_sd_state, *act_sd_state;
        int i, err;
 
+       /*
+        * FIXME: Drivers are not supposed to use __v4l2_subdev_state_alloc()
+        * but atomisp needs this for try_fmt on its /dev/video# node since
+        * it emulates a normal v4l2 device there, passing through try_fmt /
+        * set_fmt to the sensor.
+        */
+       try_sd_state = __v4l2_subdev_state_alloc(input->camera,
+                               "atomisp:try_sd_state->lock", &try_sd_state_key);
+       if (IS_ERR(try_sd_state))
+               return;
+
+       input->try_sd_state = try_sd_state;
+
+       act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
+
        mbus_code_enum.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-       err = v4l2_subdev_call(input->camera, pad, enum_mbus_code, NULL, &mbus_code_enum);
+       err = v4l2_subdev_call(input->camera, pad, enum_mbus_code,
+                              act_sd_state, &mbus_code_enum);
        if (!err)
                input->code = mbus_code_enum.code;
 
        sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        sel.target = V4L2_SEL_TGT_NATIVE_SIZE;
-       err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel);
+       err = v4l2_subdev_call(input->camera, pad, get_selection,
+                              act_sd_state, &sel);
        if (err)
-               return;
+               goto unlock_act_sd_state;
 
        input->native_rect = sel.r;
 
        sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        sel.target = V4L2_SEL_TGT_CROP_DEFAULT;
-       err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel);
+       err = v4l2_subdev_call(input->camera, pad, get_selection,
+                              act_sd_state, &sel);
        if (err)
-               return;
+               goto unlock_act_sd_state;
 
        input->active_rect = sel.r;
 
@@ -973,7 +993,8 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input)
                fse.code = input->code;
                fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 
-               err = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse);
+               err = v4l2_subdev_call(input->camera, pad, enum_frame_size,
+                                      act_sd_state, &fse);
                if (err)
                        break;
 
@@ -989,22 +1010,26 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input)
         * for padding, set the crop rect to cover the entire sensor instead
         * of only the default active area.
         *
-        * Do this for both try and active formats since the try_crop rect in
-        * pad_cfg may influence (clamp) future try_fmt calls with which == try.
+        * Do this for both try and active formats since the crop rect in
+        * try_sd_state may influence (clamp size) in calls with which == try.
         */
        sel.which = V4L2_SUBDEV_FORMAT_TRY;
        sel.target = V4L2_SEL_TGT_CROP;
        sel.r = input->native_rect;
-       err = v4l2_subdev_call(input->camera, pad, set_selection, &sd_state, &sel);
+       v4l2_subdev_lock_state(input->try_sd_state);
+       err = v4l2_subdev_call(input->camera, pad, set_selection,
+                              input->try_sd_state, &sel);
+       v4l2_subdev_unlock_state(input->try_sd_state);
        if (err)
-               return;
+               goto unlock_act_sd_state;
 
        sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        sel.target = V4L2_SEL_TGT_CROP;
        sel.r = input->native_rect;
-       err = v4l2_subdev_call(input->camera, pad, set_selection, NULL, &sel);
+       err = v4l2_subdev_call(input->camera, pad, set_selection,
+                              act_sd_state, &sel);
        if (err)
-               return;
+               goto unlock_act_sd_state;
 
        dev_info(input->camera->dev, "Supports crop native %dx%d active %dx%d binning %d\n",
                 input->native_rect.width, input->native_rect.height,
@@ -1012,6 +1037,10 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input)
                 input->binning_support);
 
        input->crop_support = true;
+
+unlock_act_sd_state:
+       if (act_sd_state)
+               v4l2_subdev_unlock_state(act_sd_state);
 }
 
 int atomisp_register_device_nodes(struct atomisp_device *isp)
index a5f58988130a15c921e45570298edfbe212273ba..c1fbcdd1618264f0cd09f5e4078ac600ad6dc22a 100644 (file)
@@ -759,6 +759,29 @@ static ssize_t emulate_tas_store(struct config_item *item,
        return count;
 }
 
+static int target_try_configure_unmap(struct se_device *dev,
+                                     const char *config_opt)
+{
+       if (!dev->transport->configure_unmap) {
+               pr_err("Generic Block Discard not supported\n");
+               return -ENOSYS;
+       }
+
+       if (!target_dev_configured(dev)) {
+               pr_err("Generic Block Discard setup for %s requires device to be configured\n",
+                      config_opt);
+               return -ENODEV;
+       }
+
+       if (!dev->transport->configure_unmap(dev)) {
+               pr_err("Generic Block Discard setup for %s failed\n",
+                      config_opt);
+               return -ENOSYS;
+       }
+
+       return 0;
+}
+
 static ssize_t emulate_tpu_store(struct config_item *item,
                const char *page, size_t count)
 {
@@ -776,11 +799,9 @@ static ssize_t emulate_tpu_store(struct config_item *item,
         * Discard supported is detected iblock_create_virtdevice().
         */
        if (flag && !da->max_unmap_block_desc_count) {
-               if (!dev->transport->configure_unmap ||
-                   !dev->transport->configure_unmap(dev)) {
-                       pr_err("Generic Block Discard not supported\n");
-                       return -ENOSYS;
-               }
+               ret = target_try_configure_unmap(dev, "emulate_tpu");
+               if (ret)
+                       return ret;
        }
 
        da->emulate_tpu = flag;
@@ -806,11 +827,9 @@ static ssize_t emulate_tpws_store(struct config_item *item,
         * Discard supported is detected iblock_create_virtdevice().
         */
        if (flag && !da->max_unmap_block_desc_count) {
-               if (!dev->transport->configure_unmap ||
-                   !dev->transport->configure_unmap(dev)) {
-                       pr_err("Generic Block Discard not supported\n");
-                       return -ENOSYS;
-               }
+               ret = target_try_configure_unmap(dev, "emulate_tpws");
+               if (ret)
+                       return ret;
        }
 
        da->emulate_tpws = flag;
@@ -1022,12 +1041,9 @@ static ssize_t unmap_zeroes_data_store(struct config_item *item,
         * Discard supported is detected iblock_configure_device().
         */
        if (flag && !da->max_unmap_block_desc_count) {
-               if (!dev->transport->configure_unmap ||
-                   !dev->transport->configure_unmap(dev)) {
-                       pr_err("dev[%p]: Thin Provisioning LBPRZ will not be set because max_unmap_block_desc_count is zero\n",
-                              da->da_dev);
-                       return -ENOSYS;
-               }
+               ret = target_try_configure_unmap(dev, "unmap_zeroes_data");
+               if (ret)
+                       return ret;
        }
        da->unmap_zeroes_data = flag;
        pr_debug("dev[%p]: SE Device Thin Provisioning LBPRZ bit: %d\n",
index 87e4795275fe6772e0497e8c50650d4a1835b1af..6f798f6a2b8488ca5011fe813733ffc8b5942f48 100644 (file)
@@ -203,7 +203,7 @@ struct tb_regs_switch_header {
 #define ROUTER_CS_5_WOP                                BIT(1)
 #define ROUTER_CS_5_WOU                                BIT(2)
 #define ROUTER_CS_5_WOD                                BIT(3)
-#define ROUTER_CS_5_C3S                                BIT(23)
+#define ROUTER_CS_5_CNS                                BIT(23)
 #define ROUTER_CS_5_PTO                                BIT(24)
 #define ROUTER_CS_5_UTO                                BIT(25)
 #define ROUTER_CS_5_HCO                                BIT(26)
index f8f0d24ff6e4629856ea8a59b3941b79633d1781..1515eff8cc3e23434202fead2a9aa038080111d6 100644 (file)
@@ -290,7 +290,7 @@ int usb4_switch_setup(struct tb_switch *sw)
        }
 
        /* TBT3 supported by the CM */
-       val |= ROUTER_CS_5_C3S;
+       val &= ~ROUTER_CS_5_CNS;
 
        return tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1);
 }
index cd258922bd780019609fee227f55d84ed3a04246..2dda737b1660bd7bd6f576d2146440d97e945047 100644 (file)
@@ -302,7 +302,7 @@ static void pci1xxxx_process_read_data(struct uart_port *port,
         * to read, the data is received one byte at a time.
         */
        while (valid_burst_count--) {
-               if (*buff_index >= (RX_BUF_SIZE - UART_BURST_SIZE))
+               if (*buff_index > (RX_BUF_SIZE - UART_BURST_SIZE))
                        break;
                burst_buf = (u32 *)&rx_buff[*buff_index];
                *burst_buf = readl(port->membase + UART_RX_BURST_FIFO);
index 3ec725555bcc1e6eb2843a186a5c49cba1ab0b42..4749331fe618cad7c0af98630f90021b8244bd07 100644 (file)
@@ -605,13 +605,16 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s)
                return;
        }
 
-       pending = uart_port_tx(&s->port, ch,
+       pending = uart_port_tx_flags(&s->port, ch, UART_TX_NOSTOP,
                !(mxs_read(s, REG_STAT) & AUART_STAT_TXFF),
                mxs_write(ch, s, REG_DATA));
        if (pending)
                mxs_set(AUART_INTR_TXIEN, s, REG_INTR);
        else
                mxs_clr(AUART_INTR_TXIEN, s, REG_INTR);
+
+       if (uart_tx_stopped(&s->port))
+               mxs_auart_stop_tx(&s->port);
 }
 
 static void mxs_auart_rx_char(struct mxs_auart_port *s)
index 029d017fc1b66b5c6695096016b54983e26b3e5f..d77b25b79ae3ec5c949912eb88b2433472180be0 100644 (file)
@@ -3057,7 +3057,7 @@ bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd)
  */
 static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag)
 {
-       u32 mask = 1U << task_tag;
+       u32 mask;
        unsigned long flags;
        int err;
 
@@ -3075,6 +3075,8 @@ static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag)
                return 0;
        }
 
+       mask = 1U << task_tag;
+
        /* clear outstanding transaction before retry */
        spin_lock_irqsave(hba->host->host_lock, flags);
        ufshcd_utrl_clear(hba, mask);
@@ -6352,7 +6354,6 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
                ufshcd_hold(hba);
                if (!ufshcd_is_clkgating_allowed(hba))
                        ufshcd_setup_clocks(hba, true);
-               ufshcd_release(hba);
                pm_op = hba->is_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM;
                ufshcd_vops_resume(hba, pm_op);
        } else {
index e3eea965e57bfd3d32fa6b1cb52fd4072734a30d..e120611a5174f7589ac124641a7b279654babff6 100644 (file)
 /* Global HWPARAMS4 Register */
 #define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n)   (((n) & (0x0f << 13)) >> 13)
 #define DWC3_MAX_HIBER_SCRATCHBUFS             15
-#define DWC3_EXT_BUFF_CONTROL          BIT(21)
 
 /* Global HWPARAMS6 Register */
 #define DWC3_GHWPARAMS6_BCSUPPORT              BIT(14)
index 564976b3e2b911e6709758cc8bdbe0c85df86562..4c8dd67246788d3839c59fa5c284113ac61ffea8 100644 (file)
@@ -673,12 +673,6 @@ static int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, unsigned int action)
                params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(bInterval_m1);
        }
 
-       if (dep->endpoint.fifo_mode) {
-               if (!(dwc->hwparams.hwparams4 & DWC3_EXT_BUFF_CONTROL))
-                       return -EINVAL;
-               params.param1 |= DWC3_DEPCFG_EBC_HWO_NOWB | DWC3_DEPCFG_USE_EBC;
-       }
-
        return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, &params);
 }
 
index fd7a4e94397e64ccc74e362e5d73319918fdbae6..55a56cf67d7364998f9f4a42fd95e5d856cd105c 100644 (file)
@@ -26,8 +26,6 @@ struct dwc3;
 #define DWC3_DEPCFG_XFER_NOT_READY_EN  BIT(10)
 #define DWC3_DEPCFG_FIFO_ERROR_EN      BIT(11)
 #define DWC3_DEPCFG_STREAM_EVENT_EN    BIT(13)
-#define DWC3_DEPCFG_EBC_HWO_NOWB       BIT(14)
-#define DWC3_DEPCFG_USE_EBC            BIT(15)
 #define DWC3_DEPCFG_BINTERVAL_M1(n)    (((n) & 0xff) << 16)
 #define DWC3_DEPCFG_STREAM_CAPABLE     BIT(24)
 #define DWC3_DEPCFG_EP_NUMBER(n)       (((n) & 0x1f) << 25)
index b8cfea7812d6b61110cc5e42fe4249d4578dc721..3b9f080109d7e46da11e4efb73a46554d7ff416f 100644 (file)
@@ -923,8 +923,8 @@ static void shutdown_pirq(struct irq_data *data)
                return;
 
        do_mask(info, EVT_MASK_REASON_EXPLICIT);
-       xen_evtchn_close(evtchn);
        xen_irq_info_cleanup(info);
+       xen_evtchn_close(evtchn);
 }
 
 static void enable_pirq(struct irq_data *data)
@@ -956,6 +956,7 @@ EXPORT_SYMBOL_GPL(xen_irq_from_gsi);
 static void __unbind_from_irq(struct irq_info *info, unsigned int irq)
 {
        evtchn_port_t evtchn;
+       bool close_evtchn = false;
 
        if (!info) {
                xen_irq_free_desc(irq);
@@ -975,7 +976,7 @@ static void __unbind_from_irq(struct irq_info *info, unsigned int irq)
                struct xenbus_device *dev;
 
                if (!info->is_static)
-                       xen_evtchn_close(evtchn);
+                       close_evtchn = true;
 
                switch (info->type) {
                case IRQT_VIRQ:
@@ -995,6 +996,9 @@ static void __unbind_from_irq(struct irq_info *info, unsigned int irq)
                }
 
                xen_irq_info_cleanup(info);
+
+               if (close_evtchn)
+                       xen_evtchn_close(evtchn);
        }
 
        xen_free_irq(info);
index 26ffb8755ffb5da27bd1eb38ceeb59ca06c473ed..f93f73ecefeee4b2b052a3ac758a8fbf9fdc11ae 100644 (file)
@@ -317,7 +317,7 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv,
                rc = -EFAULT;
                goto out_free;
        }
-       if (copy_to_user(arg->gref_ids, gref_ids,
+       if (copy_to_user(arg->gref_ids_flex, gref_ids,
                        sizeof(gref_ids[0]) * op.count)) {
                rc = -EFAULT;
                goto out_free;
index 50865527314538a8bedbde0f2590fbbb4afce3ce..c63f317e3df3de111b63a6f1b58feefca7de998b 100644 (file)
@@ -65,7 +65,7 @@ struct pcpu {
        uint32_t flags;
 };
 
-static struct bus_type xen_pcpu_subsys = {
+static const struct bus_type xen_pcpu_subsys = {
        .name = "xen_cpu",
        .dev_name = "xen_cpu",
 };
index 35b6e306026a4bfa1829f39f9b63ee8568f332d3..67dfa47788649328f6ad5783902f7dbcee9efa48 100644 (file)
@@ -1223,18 +1223,13 @@ struct privcmd_kernel_ioreq *alloc_ioreq(struct privcmd_ioeventfd *ioeventfd)
        kioreq->ioreq = (struct ioreq *)(page_to_virt(pages[0]));
        mmap_write_unlock(mm);
 
-       size = sizeof(*ports) * kioreq->vcpus;
-       ports = kzalloc(size, GFP_KERNEL);
-       if (!ports) {
-               ret = -ENOMEM;
+       ports = memdup_array_user(u64_to_user_ptr(ioeventfd->ports),
+                                 kioreq->vcpus, sizeof(*ports));
+       if (IS_ERR(ports)) {
+               ret = PTR_ERR(ports);
                goto error_kfree;
        }
 
-       if (copy_from_user(ports, u64_to_user_ptr(ioeventfd->ports), size)) {
-               ret = -EFAULT;
-               goto error_kfree_ports;
-       }
-
        for (i = 0; i < kioreq->vcpus; i++) {
                kioreq->ports[i].vcpu = i;
                kioreq->ports[i].port = ports[i];
@@ -1256,7 +1251,7 @@ struct privcmd_kernel_ioreq *alloc_ioreq(struct privcmd_ioeventfd *ioeventfd)
 error_unbind:
        while (--i >= 0)
                unbind_from_irqhandler(irq_from_evtchn(ports[i]), &kioreq->ports[i]);
-error_kfree_ports:
+
        kfree(ports);
 error_kfree:
        kfree(kioreq);
index 8cd583db20b1737144dbfb562f83a505d72c1f3d..b293d7652f15593532b9483422bcc56cbaae8cd9 100644 (file)
@@ -237,7 +237,7 @@ static const struct attribute_group *balloon_groups[] = {
        NULL
 };
 
-static struct bus_type balloon_subsys = {
+static const struct bus_type balloon_subsys = {
        .name = BALLOON_CLASS_NAME,
        .dev_name = BALLOON_CLASS_NAME,
 };
index 32835b4b9bc5030ad3e81ae411d56635f8d6a696..51b3124b0d56c98c316c58fa73d92c07e59b726a 100644 (file)
@@ -116,14 +116,15 @@ EXPORT_SYMBOL_GPL(xenbus_strstate);
  * @dev: xenbus device
  * @path: path to watch
  * @watch: watch to register
+ * @will_handle: events queuing determine callback
  * @callback: callback to register
  *
  * Register a @watch on the given path, using the given xenbus_watch structure
- * for storage, and the given @callback function as the callback.  On success,
- * the given @path will be saved as @watch->node, and remains the
- * caller's to free.  On error, @watch->node will
- * be NULL, the device will switch to %XenbusStateClosing, and the error will
- * be saved in the store.
+ * for storage, @will_handle function as the callback to determine if each
+ * event need to be queued, and the given @callback function as the callback.
+ * On success, the given @path will be saved as @watch->node, and remains the
+ * caller's to free.  On error, @watch->node will be NULL, the device will
+ * switch to %XenbusStateClosing, and the error will be saved in the store.
  *
  * Returns: %0 on success or -errno on error
  */
@@ -158,11 +159,13 @@ EXPORT_SYMBOL_GPL(xenbus_watch_path);
  * xenbus_watch_pathfmt - register a watch on a sprintf-formatted path
  * @dev: xenbus device
  * @watch: watch to register
+ * @will_handle: events queuing determine callback
  * @callback: callback to register
  * @pathfmt: format of path to watch
  *
  * Register a watch on the given @path, using the given xenbus_watch
- * structure for storage, and the given @callback function as the
+ * structure for storage, @will_handle function as the callback to determine if
+ * each event need to be queued, and the given @callback function as the
  * callback.  On success, the watched path (@path/@path2) will be saved
  * as @watch->node, and becomes the caller's to kfree().
  * On error, watch->node will be NULL, so the caller has nothing to
index 3a4c24c28e7fa06deff38f6bb0b240a5daacda8c..3dc8630ff9fe139bd44317d72502ed9bf1f73751 100644 (file)
@@ -455,6 +455,7 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
        if (IS_ERR(victim))
                return PTR_ERR(victim);
 
+       dir = d_inode(path.dentry);
        if (victim->d_sb->s_fs_info != c) {
                ret = -EXDEV;
                goto err;
@@ -463,14 +464,13 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
                ret = -ENOENT;
                goto err;
        }
-       dir = d_inode(path.dentry);
        ret = __bch2_unlink(dir, victim, true);
        if (!ret) {
                fsnotify_rmdir(dir, victim);
                d_delete(victim);
        }
-       inode_unlock(dir);
 err:
+       inode_unlock(dir);
        dput(victim);
        path_put(&path);
        return ret;
index b2be565bb8f214bc2ac4ebd6efac324ac20b7241..64df11ab422bf455560bad095973cc6e5a296697 100644 (file)
@@ -17,7 +17,7 @@
  * Rust and rustc has issues with u128.
  */
 
-#if defined(__SIZEOF_INT128__) && defined(__KERNEL__)
+#if defined(__SIZEOF_INT128__) && defined(__KERNEL__) && !defined(CONFIG_PARISC)
 
 typedef struct {
        unsigned __int128 v;
index b1c867aa2b58e6f097cba1e4eedc37f55a58cc93..9220d7de10db67f6cd4a36040af7fe557756230b 100644 (file)
@@ -53,9 +53,9 @@ int bch2_run_thread_with_file(struct thread_with_file *thr,
        if (ret)
                goto err;
 
-       fd_install(fd, file);
        get_task_struct(thr->task);
        wake_up_process(thr->task);
+       fd_install(fd, file);
        return fd;
 err:
        if (fd >= 0)
index 56b815fd9fc6ee5a541aa8e7007f3c00025c493d..231003b405efc304a4cefa61a6e4e2f30b4b9466 100644 (file)
@@ -418,14 +418,15 @@ static inline void bch2_time_stats_update_one(struct bch2_time_stats *stats,
                bch2_quantiles_update(&stats->quantiles, duration);
        }
 
-       if (time_after64(end, stats->last_event)) {
+       if (stats->last_event && time_after64(end, stats->last_event)) {
                freq = end - stats->last_event;
                mean_and_variance_update(&stats->freq_stats, freq);
                mean_and_variance_weighted_update(&stats->freq_stats_weighted, freq);
                stats->max_freq = max(stats->max_freq, freq);
                stats->min_freq = min(stats->min_freq, freq);
-               stats->last_event = end;
        }
+
+       stats->last_event = end;
 }
 
 static void __bch2_time_stats_clear_buffer(struct bch2_time_stats *stats,
index a9be9ac9922225bb32801aec5834c9e9d87ffc97..378d9103a2072b1628e66d850a42b9254be72b36 100644 (file)
@@ -1455,6 +1455,7 @@ out:
  */
 void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
 {
+       LIST_HEAD(retry_list);
        struct btrfs_block_group *block_group;
        struct btrfs_space_info *space_info;
        struct btrfs_trans_handle *trans;
@@ -1476,6 +1477,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
 
        spin_lock(&fs_info->unused_bgs_lock);
        while (!list_empty(&fs_info->unused_bgs)) {
+               u64 used;
                int trimming;
 
                block_group = list_first_entry(&fs_info->unused_bgs,
@@ -1511,9 +1513,9 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
                        goto next;
                }
 
+               spin_lock(&space_info->lock);
                spin_lock(&block_group->lock);
-               if (block_group->reserved || block_group->pinned ||
-                   block_group->used || block_group->ro ||
+               if (btrfs_is_block_group_used(block_group) || block_group->ro ||
                    list_is_singular(&block_group->list)) {
                        /*
                         * We want to bail if we made new allocations or have
@@ -1523,10 +1525,49 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
                         */
                        trace_btrfs_skip_unused_block_group(block_group);
                        spin_unlock(&block_group->lock);
+                       spin_unlock(&space_info->lock);
                        up_write(&space_info->groups_sem);
                        goto next;
                }
+
+               /*
+                * The block group may be unused but there may be space reserved
+                * accounting with the existence of that block group, that is,
+                * space_info->bytes_may_use was incremented by a task but no
+                * space was yet allocated from the block group by the task.
+                * That space may or may not be allocated, as we are generally
+                * pessimistic about space reservation for metadata as well as
+                * for data when using compression (as we reserve space based on
+                * the worst case, when data can't be compressed, and before
+                * actually attempting compression, before starting writeback).
+                *
+                * So check if the total space of the space_info minus the size
+                * of this block group is less than the used space of the
+                * space_info - if that's the case, then it means we have tasks
+                * that might be relying on the block group in order to allocate
+                * extents, and add back the block group to the unused list when
+                * we finish, so that we retry later in case no tasks ended up
+                * needing to allocate extents from the block group.
+                */
+               used = btrfs_space_info_used(space_info, true);
+               if (space_info->total_bytes - block_group->length < used) {
+                       /*
+                        * Add a reference for the list, compensate for the ref
+                        * drop under the "next" label for the
+                        * fs_info->unused_bgs list.
+                        */
+                       btrfs_get_block_group(block_group);
+                       list_add_tail(&block_group->bg_list, &retry_list);
+
+                       trace_btrfs_skip_unused_block_group(block_group);
+                       spin_unlock(&block_group->lock);
+                       spin_unlock(&space_info->lock);
+                       up_write(&space_info->groups_sem);
+                       goto next;
+               }
+
                spin_unlock(&block_group->lock);
+               spin_unlock(&space_info->lock);
 
                /* We don't want to force the issue, only flip if it's ok. */
                ret = inc_block_group_ro(block_group, 0);
@@ -1650,12 +1691,16 @@ next:
                btrfs_put_block_group(block_group);
                spin_lock(&fs_info->unused_bgs_lock);
        }
+       list_splice_tail(&retry_list, &fs_info->unused_bgs);
        spin_unlock(&fs_info->unused_bgs_lock);
        mutex_unlock(&fs_info->reclaim_bgs_lock);
        return;
 
 flip_async:
        btrfs_end_transaction(trans);
+       spin_lock(&fs_info->unused_bgs_lock);
+       list_splice_tail(&retry_list, &fs_info->unused_bgs);
+       spin_unlock(&fs_info->unused_bgs_lock);
        mutex_unlock(&fs_info->reclaim_bgs_lock);
        btrfs_put_block_group(block_group);
        btrfs_discard_punt_unused_bgs_list(fs_info);
@@ -2684,6 +2729,37 @@ next:
                btrfs_dec_delayed_refs_rsv_bg_inserts(fs_info);
                list_del_init(&block_group->bg_list);
                clear_bit(BLOCK_GROUP_FLAG_NEW, &block_group->runtime_flags);
+
+               /*
+                * If the block group is still unused, add it to the list of
+                * unused block groups. The block group may have been created in
+                * order to satisfy a space reservation, in which case the
+                * extent allocation only happens later. But often we don't
+                * actually need to allocate space that we previously reserved,
+                * so the block group may become unused for a long time. For
+                * example for metadata we generally reserve space for a worst
+                * possible scenario, but then don't end up allocating all that
+                * space or none at all (due to no need to COW, extent buffers
+                * were already COWed in the current transaction and still
+                * unwritten, tree heights lower than the maximum possible
+                * height, etc). For data we generally reserve the axact amount
+                * of space we are going to allocate later, the exception is
+                * when using compression, as we must reserve space based on the
+                * uncompressed data size, because the compression is only done
+                * when writeback triggered and we don't know how much space we
+                * are actually going to need, so we reserve the uncompressed
+                * size because the data may be uncompressible in the worst case.
+                */
+               if (ret == 0) {
+                       bool used;
+
+                       spin_lock(&block_group->lock);
+                       used = btrfs_is_block_group_used(block_group);
+                       spin_unlock(&block_group->lock);
+
+                       if (!used)
+                               btrfs_mark_bg_unused(block_group);
+               }
        }
        btrfs_trans_release_chunk_metadata(trans);
 }
index c4a1f01cc1c240d108702fc8899de9efe00da613..962b11983901a86ae16add7962c5ea5a26796b6f 100644 (file)
@@ -257,6 +257,13 @@ static inline u64 btrfs_block_group_end(struct btrfs_block_group *block_group)
        return (block_group->start + block_group->length);
 }
 
+static inline bool btrfs_is_block_group_used(const struct btrfs_block_group *bg)
+{
+       lockdep_assert_held(&bg->lock);
+
+       return (bg->used > 0 || bg->reserved > 0 || bg->pinned > 0);
+}
+
 static inline bool btrfs_is_block_group_data_only(
                                        struct btrfs_block_group *block_group)
 {
index 2833e8ef4c098f680a4883d41a1e925dc477bc2f..acf9f4b6c044025fe2ef288e99716d0373d01f31 100644 (file)
@@ -245,7 +245,6 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
        struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
        u64 reserve_size = 0;
        u64 qgroup_rsv_size = 0;
-       u64 csum_leaves;
        unsigned outstanding_extents;
 
        lockdep_assert_held(&inode->lock);
@@ -260,10 +259,12 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
                                                outstanding_extents);
                reserve_size += btrfs_calc_metadata_size(fs_info, 1);
        }
-       csum_leaves = btrfs_csum_bytes_to_leaves(fs_info,
-                                                inode->csum_bytes);
-       reserve_size += btrfs_calc_insert_metadata_size(fs_info,
-                                                       csum_leaves);
+       if (!(inode->flags & BTRFS_INODE_NODATASUM)) {
+               u64 csum_leaves;
+
+               csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, inode->csum_bytes);
+               reserve_size += btrfs_calc_insert_metadata_size(fs_info, csum_leaves);
+       }
        /*
         * For qgroup rsv, the calculation is very simple:
         * account one nodesize for each outstanding extent
@@ -278,14 +279,20 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
        spin_unlock(&block_rsv->lock);
 }
 
-static void calc_inode_reservations(struct btrfs_fs_info *fs_info,
+static void calc_inode_reservations(struct btrfs_inode *inode,
                                    u64 num_bytes, u64 disk_num_bytes,
                                    u64 *meta_reserve, u64 *qgroup_reserve)
 {
+       struct btrfs_fs_info *fs_info = inode->root->fs_info;
        u64 nr_extents = count_max_extents(fs_info, num_bytes);
-       u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, disk_num_bytes);
+       u64 csum_leaves;
        u64 inode_update = btrfs_calc_metadata_size(fs_info, 1);
 
+       if (inode->flags & BTRFS_INODE_NODATASUM)
+               csum_leaves = 0;
+       else
+               csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, disk_num_bytes);
+
        *meta_reserve = btrfs_calc_insert_metadata_size(fs_info,
                                                nr_extents + csum_leaves);
 
@@ -337,7 +344,7 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
         * everything out and try again, which is bad.  This way we just
         * over-reserve slightly, and clean up the mess when we are done.
         */
-       calc_inode_reservations(fs_info, num_bytes, disk_num_bytes,
+       calc_inode_reservations(inode, num_bytes, disk_num_bytes,
                                &meta_reserve, &qgroup_reserve);
        ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_reserve, true,
                                                 noflush);
@@ -359,7 +366,8 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
        nr_extents = count_max_extents(fs_info, num_bytes);
        spin_lock(&inode->lock);
        btrfs_mod_outstanding_extents(inode, nr_extents);
-       inode->csum_bytes += disk_num_bytes;
+       if (!(inode->flags & BTRFS_INODE_NODATASUM))
+               inode->csum_bytes += disk_num_bytes;
        btrfs_calculate_inode_block_rsv_size(fs_info, inode);
        spin_unlock(&inode->lock);
 
@@ -393,7 +401,8 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes,
 
        num_bytes = ALIGN(num_bytes, fs_info->sectorsize);
        spin_lock(&inode->lock);
-       inode->csum_bytes -= num_bytes;
+       if (!(inode->flags & BTRFS_INODE_NODATASUM))
+               inode->csum_bytes -= num_bytes;
        btrfs_calculate_inode_block_rsv_size(fs_info, inode);
        spin_unlock(&inode->lock);
 
index c6907d533fe83912576fd92283658539e0abbb81..e71ef97d0a7cabb236e8cbd073667b2e3d143dca 100644 (file)
@@ -1336,8 +1336,17 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info,
 again:
        root = btrfs_lookup_fs_root(fs_info, objectid);
        if (root) {
-               /* Shouldn't get preallocated anon_dev for cached roots */
-               ASSERT(!anon_dev);
+               /*
+                * Some other caller may have read out the newly inserted
+                * subvolume already (for things like backref walk etc).  Not
+                * that common but still possible.  In that case, we just need
+                * to free the anon_dev.
+                */
+               if (unlikely(anon_dev)) {
+                       free_anon_bdev(anon_dev);
+                       anon_dev = 0;
+               }
+
                if (check_ref && btrfs_root_refs(&root->root_item) == 0) {
                        btrfs_put_root(root);
                        return ERR_PTR(-ENOENT);
index 1eb93d3962aac4608cda0255ea31d7e53dbc8da2..f88e0ca8331d9b5448e8e07c89e5e66395c782b3 100644 (file)
@@ -3184,8 +3184,23 @@ out:
                        unwritten_start += logical_len;
                clear_extent_uptodate(io_tree, unwritten_start, end, NULL);
 
-               /* Drop extent maps for the part of the extent we didn't write. */
-               btrfs_drop_extent_map_range(inode, unwritten_start, end, false);
+               /*
+                * Drop extent maps for the part of the extent we didn't write.
+                *
+                * We have an exception here for the free_space_inode, this is
+                * because when we do btrfs_get_extent() on the free space inode
+                * we will search the commit root.  If this is a new block group
+                * we won't find anything, and we will trip over the assert in
+                * writepage where we do ASSERT(em->block_start !=
+                * EXTENT_MAP_HOLE).
+                *
+                * Theoretically we could also skip this for any NOCOW extent as
+                * we don't mess with the extent map tree in the NOCOW case, but
+                * for now simply skip this if we are the free space inode.
+                */
+               if (!btrfs_is_free_space_inode(inode))
+                       btrfs_drop_extent_map_range(inode, unwritten_start,
+                                                   end, false);
 
                /*
                 * If the ordered extent had an IOERR or something else went
@@ -10273,6 +10288,13 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
        if (encoded->encryption != BTRFS_ENCODED_IO_ENCRYPTION_NONE)
                return -EINVAL;
 
+       /*
+        * Compressed extents should always have checksums, so error out if we
+        * have a NOCOW file or inode was created while mounted with NODATASUM.
+        */
+       if (inode->flags & BTRFS_INODE_NODATASUM)
+               return -EINVAL;
+
        orig_count = iov_iter_count(from);
 
        /* The extent size must be sane. */
index dfed9dd9c2d75b8205531b030c220b42820e77ce..ac3316e0d11c3a42835dc8a2094b00a16019bd64 100644 (file)
@@ -3815,6 +3815,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)
                goto out;
        }
 
+       if (sa->create && is_fstree(sa->qgroupid)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        trans = btrfs_join_transaction(root);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
index 63b426cc77989670e0f7890a1cb75a17348e96cb..5470e1cdf10c5348df676cd290bef45811a46019 100644 (file)
@@ -1736,6 +1736,15 @@ out:
        return ret;
 }
 
+static bool qgroup_has_usage(struct btrfs_qgroup *qgroup)
+{
+       return (qgroup->rfer > 0 || qgroup->rfer_cmpr > 0 ||
+               qgroup->excl > 0 || qgroup->excl_cmpr > 0 ||
+               qgroup->rsv.values[BTRFS_QGROUP_RSV_DATA] > 0 ||
+               qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC] > 0 ||
+               qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > 0);
+}
+
 int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
 {
        struct btrfs_fs_info *fs_info = trans->fs_info;
@@ -1755,6 +1764,11 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
                goto out;
        }
 
+       if (is_fstree(qgroupid) && qgroup_has_usage(qgroup)) {
+               ret = -EBUSY;
+               goto out;
+       }
+
        /* Check if there are no children of this qgroup */
        if (!list_empty(&qgroup->members)) {
                ret = -EBUSY;
index 2d7519a6ce72d3c58e70b1cb567258e642604a87..7902298c1f25bbee1586a97f2223f3c079e3a8fb 100644 (file)
@@ -8111,7 +8111,7 @@ long btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg)
        }
 
        if (arg->flags & ~BTRFS_SEND_FLAG_MASK) {
-               ret = -EINVAL;
+               ret = -EOPNOTSUPP;
                goto out;
        }
 
index 5b3333ceef04818dbf98270da4bb84c99e5c70f8..c52807d97efa553b0b5e4765e11606a8ce644161 100644 (file)
@@ -564,56 +564,22 @@ static int btrfs_reserve_trans_metadata(struct btrfs_fs_info *fs_info,
                                        u64 num_bytes,
                                        u64 *delayed_refs_bytes)
 {
-       struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv;
        struct btrfs_space_info *si = fs_info->trans_block_rsv.space_info;
-       u64 extra_delayed_refs_bytes = 0;
-       u64 bytes;
+       u64 bytes = num_bytes + *delayed_refs_bytes;
        int ret;
 
-       /*
-        * If there's a gap between the size of the delayed refs reserve and
-        * its reserved space, than some tasks have added delayed refs or bumped
-        * its size otherwise (due to block group creation or removal, or block
-        * group item update). Also try to allocate that gap in order to prevent
-        * using (and possibly abusing) the global reserve when committing the
-        * transaction.
-        */
-       if (flush == BTRFS_RESERVE_FLUSH_ALL &&
-           !btrfs_block_rsv_full(delayed_refs_rsv)) {
-               spin_lock(&delayed_refs_rsv->lock);
-               if (delayed_refs_rsv->size > delayed_refs_rsv->reserved)
-                       extra_delayed_refs_bytes = delayed_refs_rsv->size -
-                               delayed_refs_rsv->reserved;
-               spin_unlock(&delayed_refs_rsv->lock);
-       }
-
-       bytes = num_bytes + *delayed_refs_bytes + extra_delayed_refs_bytes;
-
        /*
         * We want to reserve all the bytes we may need all at once, so we only
         * do 1 enospc flushing cycle per transaction start.
         */
        ret = btrfs_reserve_metadata_bytes(fs_info, si, bytes, flush);
-       if (ret == 0) {
-               if (extra_delayed_refs_bytes > 0)
-                       btrfs_migrate_to_delayed_refs_rsv(fs_info,
-                                                         extra_delayed_refs_bytes);
-               return 0;
-       }
-
-       if (extra_delayed_refs_bytes > 0) {
-               bytes -= extra_delayed_refs_bytes;
-               ret = btrfs_reserve_metadata_bytes(fs_info, si, bytes, flush);
-               if (ret == 0)
-                       return 0;
-       }
 
        /*
         * If we are an emergency flush, which can steal from the global block
         * reserve, then attempt to not reserve space for the delayed refs, as
         * we will consume space for them from the global block reserve.
         */
-       if (flush == BTRFS_RESERVE_FLUSH_ALL_STEAL) {
+       if (ret && flush == BTRFS_RESERVE_FLUSH_ALL_STEAL) {
                bytes -= *delayed_refs_bytes;
                *delayed_refs_bytes = 0;
                ret = btrfs_reserve_metadata_bytes(fs_info, si, bytes, flush);
index 168af9d000d168324fcc8355781517ddeedeefd1..3a5d69ff25fc221f20c1e37a9854021eff246bad 100644 (file)
@@ -1670,6 +1670,7 @@ out:
        }
        bitmap_free(active);
        kfree(zone_info);
+       btrfs_free_chunk_map(map);
 
        return ret;
 }
index 9c02f328c966cbdd12b8af17d7ddb9d5bb19ea38..7fb4aae97412464c54b42037f75016085d214bd3 100644 (file)
@@ -1452,7 +1452,7 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
        if (flushing & CEPH_CAP_XATTR_EXCL) {
                arg->old_xattr_buf = __ceph_build_xattrs_blob(ci);
                arg->xattr_version = ci->i_xattrs.version;
-               arg->xattr_buf = ci->i_xattrs.blob;
+               arg->xattr_buf = ceph_buffer_get(ci->i_xattrs.blob);
        } else {
                arg->xattr_buf = NULL;
                arg->old_xattr_buf = NULL;
@@ -1553,6 +1553,7 @@ static void __send_cap(struct cap_msg_args *arg, struct ceph_inode_info *ci)
        encode_cap_msg(msg, arg);
        ceph_con_send(&arg->session->s_con, msg);
        ceph_buffer_put(arg->old_xattr_buf);
+       ceph_buffer_put(arg->xattr_buf);
        if (arg->wake)
                wake_up_all(&ci->i_cap_wq);
 }
@@ -2155,6 +2156,30 @@ retry:
                      ceph_cap_string(cap->implemented),
                      ceph_cap_string(revoking));
 
+               /* completed revocation? going down and there are no caps? */
+               if (revoking) {
+                       if ((revoking & cap_used) == 0) {
+                               doutc(cl, "completed revocation of %s\n",
+                                     ceph_cap_string(cap->implemented & ~cap->issued));
+                               goto ack;
+                       }
+
+                       /*
+                        * If the "i_wrbuffer_ref" was increased by mmap or generic
+                        * cache write just before the ceph_check_caps() is called,
+                        * the Fb capability revoking will fail this time. Then we
+                        * must wait for the BDI's delayed work to flush the dirty
+                        * pages and to release the "i_wrbuffer_ref", which will cost
+                        * at most 5 seconds. That means the MDS needs to wait at
+                        * most 5 seconds to finished the Fb capability's revocation.
+                        *
+                        * Let's queue a writeback for it.
+                        */
+                       if (S_ISREG(inode->i_mode) && ci->i_wrbuffer_ref &&
+                           (revoking & CEPH_CAP_FILE_BUFFER))
+                               queue_writeback = true;
+               }
+
                if (cap == ci->i_auth_cap &&
                    (cap->issued & CEPH_CAP_FILE_WR)) {
                        /* request larger max_size from MDS? */
@@ -2182,30 +2207,6 @@ retry:
                        }
                }
 
-               /* completed revocation? going down and there are no caps? */
-               if (revoking) {
-                       if ((revoking & cap_used) == 0) {
-                               doutc(cl, "completed revocation of %s\n",
-                                     ceph_cap_string(cap->implemented & ~cap->issued));
-                               goto ack;
-                       }
-
-                       /*
-                        * If the "i_wrbuffer_ref" was increased by mmap or generic
-                        * cache write just before the ceph_check_caps() is called,
-                        * the Fb capability revoking will fail this time. Then we
-                        * must wait for the BDI's delayed work to flush the dirty
-                        * pages and to release the "i_wrbuffer_ref", which will cost
-                        * at most 5 seconds. That means the MDS needs to wait at
-                        * most 5 seconds to finished the Fb capability's revocation.
-                        *
-                        * Let's queue a writeback for it.
-                        */
-                       if (S_ISREG(inode->i_mode) && ci->i_wrbuffer_ref &&
-                           (revoking & CEPH_CAP_FILE_BUFFER))
-                               queue_writeback = true;
-               }
-
                /* want more caps from mds? */
                if (want & ~cap->mds_wanted) {
                        if (want & ~(cap->mds_wanted | cap->issued))
@@ -3215,7 +3216,6 @@ static int ceph_try_drop_cap_snap(struct ceph_inode_info *ci,
 
 enum put_cap_refs_mode {
        PUT_CAP_REFS_SYNC = 0,
-       PUT_CAP_REFS_NO_CHECK,
        PUT_CAP_REFS_ASYNC,
 };
 
@@ -3331,11 +3331,6 @@ void ceph_put_cap_refs_async(struct ceph_inode_info *ci, int had)
        __ceph_put_cap_refs(ci, had, PUT_CAP_REFS_ASYNC);
 }
 
-void ceph_put_cap_refs_no_check_caps(struct ceph_inode_info *ci, int had)
-{
-       __ceph_put_cap_refs(ci, had, PUT_CAP_REFS_NO_CHECK);
-}
-
 /*
  * Release @nr WRBUFFER refs on dirty pages for the given @snapc snap
  * context.  Adjust per-snap dirty page accounting as appropriate.
@@ -4777,7 +4772,22 @@ int ceph_drop_caps_for_unlink(struct inode *inode)
                if (__ceph_caps_dirty(ci)) {
                        struct ceph_mds_client *mdsc =
                                ceph_inode_to_fs_client(inode)->mdsc;
-                       __cap_delay_requeue_front(mdsc, ci);
+
+                       doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode,
+                             ceph_vinop(inode));
+                       spin_lock(&mdsc->cap_unlink_delay_lock);
+                       ci->i_ceph_flags |= CEPH_I_FLUSH;
+                       if (!list_empty(&ci->i_cap_delay_list))
+                               list_del_init(&ci->i_cap_delay_list);
+                       list_add_tail(&ci->i_cap_delay_list,
+                                     &mdsc->cap_unlink_delay_list);
+                       spin_unlock(&mdsc->cap_unlink_delay_lock);
+
+                       /*
+                        * Fire the work immediately, because the MDS maybe
+                        * waiting for caps release.
+                        */
+                       ceph_queue_cap_unlink_work(mdsc);
                }
        }
        spin_unlock(&ci->i_ceph_lock);
index 0c25d326afc41d9d4d8ba98d3c6c5976647bb3fe..7b2e77517f235ecd47264061c04bae2e6d0b7c83 100644 (file)
@@ -78,6 +78,8 @@ struct inode *ceph_new_inode(struct inode *dir, struct dentry *dentry,
        if (!inode)
                return ERR_PTR(-ENOMEM);
 
+       inode->i_blkbits = CEPH_FSCRYPT_BLOCK_SHIFT;
+
        if (!S_ISLNK(*mode)) {
                err = ceph_pre_init_acls(dir, mode, as_ctx);
                if (err < 0)
index 548d1de379f3570b729af9e50b67aaff65e36e14..3ab9c268a8bb398b779cc93d3da98f3d13df8fe3 100644 (file)
@@ -1089,7 +1089,7 @@ void ceph_mdsc_release_request(struct kref *kref)
        struct ceph_mds_request *req = container_of(kref,
                                                    struct ceph_mds_request,
                                                    r_kref);
-       ceph_mdsc_release_dir_caps_no_check(req);
+       ceph_mdsc_release_dir_caps_async(req);
        destroy_reply_info(&req->r_reply_info);
        if (req->r_request)
                ceph_msg_put(req->r_request);
@@ -2484,6 +2484,50 @@ void ceph_reclaim_caps_nr(struct ceph_mds_client *mdsc, int nr)
        }
 }
 
+void ceph_queue_cap_unlink_work(struct ceph_mds_client *mdsc)
+{
+       struct ceph_client *cl = mdsc->fsc->client;
+       if (mdsc->stopping)
+               return;
+
+        if (queue_work(mdsc->fsc->cap_wq, &mdsc->cap_unlink_work)) {
+                doutc(cl, "caps unlink work queued\n");
+        } else {
+                doutc(cl, "failed to queue caps unlink work\n");
+        }
+}
+
+static void ceph_cap_unlink_work(struct work_struct *work)
+{
+       struct ceph_mds_client *mdsc =
+               container_of(work, struct ceph_mds_client, cap_unlink_work);
+       struct ceph_client *cl = mdsc->fsc->client;
+
+       doutc(cl, "begin\n");
+       spin_lock(&mdsc->cap_unlink_delay_lock);
+       while (!list_empty(&mdsc->cap_unlink_delay_list)) {
+               struct ceph_inode_info *ci;
+               struct inode *inode;
+
+               ci = list_first_entry(&mdsc->cap_unlink_delay_list,
+                                     struct ceph_inode_info,
+                                     i_cap_delay_list);
+               list_del_init(&ci->i_cap_delay_list);
+
+               inode = igrab(&ci->netfs.inode);
+               if (inode) {
+                       spin_unlock(&mdsc->cap_unlink_delay_lock);
+                       doutc(cl, "on %p %llx.%llx\n", inode,
+                             ceph_vinop(inode));
+                       ceph_check_caps(ci, CHECK_CAPS_FLUSH);
+                       iput(inode);
+                       spin_lock(&mdsc->cap_unlink_delay_lock);
+               }
+       }
+       spin_unlock(&mdsc->cap_unlink_delay_lock);
+       doutc(cl, "done\n");
+}
+
 /*
  * requests
  */
@@ -4261,7 +4305,7 @@ void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req)
        }
 }
 
-void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req)
+void ceph_mdsc_release_dir_caps_async(struct ceph_mds_request *req)
 {
        struct ceph_client *cl = req->r_mdsc->fsc->client;
        int dcaps;
@@ -4269,8 +4313,7 @@ void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req)
        dcaps = xchg(&req->r_dir_caps, 0);
        if (dcaps) {
                doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
-               ceph_put_cap_refs_no_check_caps(ceph_inode(req->r_parent),
-                                               dcaps);
+               ceph_put_cap_refs_async(ceph_inode(req->r_parent), dcaps);
        }
 }
 
@@ -4306,7 +4349,7 @@ static void replay_unsafe_requests(struct ceph_mds_client *mdsc,
                if (req->r_session->s_mds != session->s_mds)
                        continue;
 
-               ceph_mdsc_release_dir_caps_no_check(req);
+               ceph_mdsc_release_dir_caps_async(req);
 
                __send_request(session, req, true);
        }
@@ -5360,6 +5403,8 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        INIT_LIST_HEAD(&mdsc->cap_delay_list);
        INIT_LIST_HEAD(&mdsc->cap_wait_list);
        spin_lock_init(&mdsc->cap_delay_lock);
+       INIT_LIST_HEAD(&mdsc->cap_unlink_delay_list);
+       spin_lock_init(&mdsc->cap_unlink_delay_lock);
        INIT_LIST_HEAD(&mdsc->snap_flush_list);
        spin_lock_init(&mdsc->snap_flush_lock);
        mdsc->last_cap_flush_tid = 1;
@@ -5368,6 +5413,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        spin_lock_init(&mdsc->cap_dirty_lock);
        init_waitqueue_head(&mdsc->cap_flushing_wq);
        INIT_WORK(&mdsc->cap_reclaim_work, ceph_cap_reclaim_work);
+       INIT_WORK(&mdsc->cap_unlink_work, ceph_cap_unlink_work);
        err = ceph_metric_init(&mdsc->metric);
        if (err)
                goto err_mdsmap;
@@ -5641,6 +5687,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
        ceph_cleanup_global_and_empty_realms(mdsc);
 
        cancel_work_sync(&mdsc->cap_reclaim_work);
+       cancel_work_sync(&mdsc->cap_unlink_work);
        cancel_delayed_work_sync(&mdsc->delayed_work); /* cancel timer */
 
        doutc(cl, "done\n");
index 2e6ddaa13d725016dc9a93c6ad1838806eac547e..03f8ff00874f727adff8b88cc8d538fc989692d8 100644 (file)
@@ -462,6 +462,8 @@ struct ceph_mds_client {
        unsigned long    last_renew_caps;  /* last time we renewed our caps */
        struct list_head cap_delay_list;   /* caps with delayed release */
        spinlock_t       cap_delay_lock;   /* protects cap_delay_list */
+       struct list_head cap_unlink_delay_list;  /* caps with delayed release for unlink */
+       spinlock_t       cap_unlink_delay_lock;  /* protects cap_unlink_delay_list */
        struct list_head snap_flush_list;  /* cap_snaps ready to flush */
        spinlock_t       snap_flush_lock;
 
@@ -475,6 +477,8 @@ struct ceph_mds_client {
        struct work_struct cap_reclaim_work;
        atomic_t           cap_reclaim_pending;
 
+       struct work_struct cap_unlink_work;
+
        /*
         * Cap reservations
         *
@@ -552,7 +556,7 @@ extern int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
                                struct inode *dir,
                                struct ceph_mds_request *req);
 extern void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req);
-extern void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req);
+extern void ceph_mdsc_release_dir_caps_async(struct ceph_mds_request *req);
 static inline void ceph_mdsc_get_request(struct ceph_mds_request *req)
 {
        kref_get(&req->r_kref);
@@ -574,6 +578,7 @@ extern void ceph_flush_cap_releases(struct ceph_mds_client *mdsc,
                                    struct ceph_mds_session *session);
 extern void ceph_queue_cap_reclaim_work(struct ceph_mds_client *mdsc);
 extern void ceph_reclaim_caps_nr(struct ceph_mds_client *mdsc, int nr);
+extern void ceph_queue_cap_unlink_work(struct ceph_mds_client *mdsc);
 extern int ceph_iterate_session_caps(struct ceph_mds_session *session,
                                     int (*cb)(struct inode *, int mds, void *),
                                     void *arg);
index b06e2bc86221bf02fe54b2aa3304be80bedc5214..b63b4cd9b5b685a930bc33673f28e7c48a93d605 100644 (file)
@@ -1255,8 +1255,6 @@ extern void ceph_take_cap_refs(struct ceph_inode_info *ci, int caps,
 extern void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps);
 extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had);
 extern void ceph_put_cap_refs_async(struct ceph_inode_info *ci, int had);
-extern void ceph_put_cap_refs_no_check_caps(struct ceph_inode_info *ci,
-                                           int had);
 extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
                                       struct ceph_snap_context *snapc);
 extern void __ceph_remove_capsnap(struct inode *inode,
index 671664fed3077f794de3a5707bd69b90cb328e78..d746866ae3b6ba79a4ed1d8b6600c29cfc28e005 100644 (file)
@@ -100,6 +100,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
        loff_t len, vma_len;
        int ret;
        struct hstate *h = hstate_file(file);
+       vm_flags_t vm_flags;
 
        /*
         * vma address alignment (but not the pgoff alignment) has
@@ -141,10 +142,20 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
        file_accessed(file);
 
        ret = -ENOMEM;
+
+       vm_flags = vma->vm_flags;
+       /*
+        * for SHM_HUGETLB, the pages are reserved in the shmget() call so skip
+        * reserving here. Note: only for SHM hugetlbfs file, the inode
+        * flag S_PRIVATE is set.
+        */
+       if (inode->i_flags & S_PRIVATE)
+               vm_flags |= VM_NORESERVE;
+
        if (!hugetlb_reserve_pages(inode,
                                vma->vm_pgoff >> huge_page_order(h),
                                len >> huge_page_shift(h), vma,
-                               vma->vm_flags))
+                               vm_flags))
                goto out;
 
        ret = 0;
@@ -1354,6 +1365,7 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par
 {
        struct hugetlbfs_fs_context *ctx = fc->fs_private;
        struct fs_parse_result result;
+       struct hstate *h;
        char *rest;
        unsigned long ps;
        int opt;
@@ -1398,11 +1410,12 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par
 
        case Opt_pagesize:
                ps = memparse(param->string, &rest);
-               ctx->hstate = size_to_hstate(ps);
-               if (!ctx->hstate) {
+               h = size_to_hstate(ps);
+               if (!h) {
                        pr_err("Unsupported page size %lu MB\n", ps / SZ_1M);
                        return -EINVAL;
                }
+               ctx->hstate = h;
                return 0;
 
        case Opt_min_size:
index 437f60e96d405861683f7e3596063d26c0e55038..5a51315c6678145467520800ceedc3378df5e7da 100644 (file)
@@ -4472,10 +4472,15 @@ static int do_mount_setattr(struct path *path, struct mount_kattr *kattr)
        /*
         * If this is an attached mount make sure it's located in the callers
         * mount namespace. If it's not don't let the caller interact with it.
-        * If this is a detached mount make sure it has an anonymous mount
-        * namespace attached to it, i.e. we've created it via OPEN_TREE_CLONE.
+        *
+        * If this mount doesn't have a parent it's most often simply a
+        * detached mount with an anonymous mount namespace. IOW, something
+        * that's simply not attached yet. But there are apparently also users
+        * that do change mount properties on the rootfs itself. That obviously
+        * neither has a parent nor is it a detached mount so we cannot
+        * unconditionally check for detached mounts.
         */
-       if (!(mnt_has_parent(mnt) ? check_mnt(mnt) : is_anon_ns(mnt->mnt_ns)))
+       if ((mnt_has_parent(mnt) || !is_anon_ns(mnt->mnt_ns)) && !check_mnt(mnt))
                goto out;
 
        /*
index 6dc6340e28529d8efe2a9bb99144ca297909e9d3..7d6c657e0409ddc62567554304e4a51779dd2934 100644 (file)
@@ -4945,10 +4945,8 @@ nfsd_break_deleg_cb(struct file_lock *fl)
         */
        fl->fl_break_time = 0;
 
-       spin_lock(&fp->fi_lock);
        fp->fi_had_conflict = true;
        nfsd_break_one_deleg(dp);
-       spin_unlock(&fp->fi_lock);
        return false;
 }
 
@@ -5557,12 +5555,13 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
        if (status)
                goto out_unlock;
 
+       status = -EAGAIN;
+       if (fp->fi_had_conflict)
+               goto out_unlock;
+
        spin_lock(&state_lock);
        spin_lock(&fp->fi_lock);
-       if (fp->fi_had_conflict)
-               status = -EAGAIN;
-       else
-               status = hash_delegation_locked(dp, fp);
+       status = hash_delegation_locked(dp, fp);
        spin_unlock(&fp->fi_lock);
        spin_unlock(&state_lock);
 
index bec33b89a075858ebf289a95fa4c83dbf6e86103..0e3fc5ba33c73d7f22deefc1cb68ee8395a1efa4 100644 (file)
@@ -107,7 +107,13 @@ static vm_fault_t nilfs_page_mkwrite(struct vm_fault *vmf)
        nilfs_transaction_commit(inode->i_sb);
 
  mapped:
-       folio_wait_stable(folio);
+       /*
+        * Since checksumming including data blocks is performed to determine
+        * the validity of the log to be written and used for recovery, it is
+        * necessary to wait for writeback to finish here, regardless of the
+        * stable write requirement of the backing device.
+        */
+       folio_wait_writeback(folio);
  out:
        sb_end_pagefault(inode->i_sb);
        return vmf_fs_error(ret);
index 0955b657938ff2ce993d92e7d8f81322ce71c2e1..a9b8d77c8c1d55b551582b826dafdcdcd047d13a 100644 (file)
@@ -472,9 +472,10 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
 
 static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
                                     struct nilfs_recovery_block *rb,
-                                    struct page *page)
+                                    loff_t pos, struct page *page)
 {
        struct buffer_head *bh_org;
+       size_t from = pos & ~PAGE_MASK;
        void *kaddr;
 
        bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize);
@@ -482,7 +483,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
                return -EIO;
 
        kaddr = kmap_atomic(page);
-       memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size);
+       memcpy(kaddr + from, bh_org->b_data, bh_org->b_size);
        kunmap_atomic(kaddr);
        brelse(bh_org);
        return 0;
@@ -521,7 +522,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
                        goto failed_inode;
                }
 
-               err = nilfs_recovery_copy_block(nilfs, rb, page);
+               err = nilfs_recovery_copy_block(nilfs, rb, pos, page);
                if (unlikely(err))
                        goto failed_page;
 
index 2590a0860eab022ba68a18b9db8fe181faab5069..2bfb08052d399972dee9fd49583b77b95104ac83 100644 (file)
@@ -1703,7 +1703,6 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci)
 
                list_for_each_entry(bh, &segbuf->sb_payload_buffers,
                                    b_assoc_buffers) {
-                       set_buffer_async_write(bh);
                        if (bh == segbuf->sb_super_root) {
                                if (bh->b_folio != bd_folio) {
                                        folio_lock(bd_folio);
@@ -1714,6 +1713,7 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci)
                                }
                                break;
                        }
+                       set_buffer_async_write(bh);
                        if (bh->b_folio != fs_folio) {
                                nilfs_begin_folio_io(fs_folio);
                                fs_folio = bh->b_folio;
@@ -1800,7 +1800,6 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
 
                list_for_each_entry(bh, &segbuf->sb_payload_buffers,
                                    b_assoc_buffers) {
-                       clear_buffer_async_write(bh);
                        if (bh == segbuf->sb_super_root) {
                                clear_buffer_uptodate(bh);
                                if (bh->b_folio != bd_folio) {
@@ -1809,6 +1808,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
                                }
                                break;
                        }
+                       clear_buffer_async_write(bh);
                        if (bh->b_folio != fs_folio) {
                                nilfs_end_folio_io(fs_folio, err);
                                fs_folio = bh->b_folio;
@@ -1896,8 +1896,9 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
                                 BIT(BH_Delay) | BIT(BH_NILFS_Volatile) |
                                 BIT(BH_NILFS_Redirected));
 
-                       set_mask_bits(&bh->b_state, clear_bits, set_bits);
                        if (bh == segbuf->sb_super_root) {
+                               set_buffer_uptodate(bh);
+                               clear_buffer_dirty(bh);
                                if (bh->b_folio != bd_folio) {
                                        folio_end_writeback(bd_folio);
                                        bd_folio = bh->b_folio;
@@ -1905,6 +1906,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
                                update_sr = true;
                                break;
                        }
+                       set_mask_bits(&bh->b_state, clear_bits, set_bits);
                        if (bh->b_folio != fs_folio) {
                                nilfs_end_folio_io(fs_folio, 0);
                                fs_folio = bh->b_folio;
index 63f70259edc0d44d6a52c946c9a90663fe16722a..7aadf5010999455e4d16e20581e2334034451e57 100644 (file)
@@ -886,7 +886,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
        struct runs_tree *run = &ni->file.run;
        struct ntfs_sb_info *sbi;
        u8 cluster_bits;
-       struct ATTRIB *attr = NULL, *attr_b;
+       struct ATTRIB *attr, *attr_b;
        struct ATTR_LIST_ENTRY *le, *le_b;
        struct mft_inode *mi, *mi_b;
        CLST hint, svcn, to_alloc, evcn1, next_svcn, asize, end, vcn0, alen;
@@ -904,12 +904,8 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
                *len = 0;
        up_read(&ni->file.run_lock);
 
-       if (*len) {
-               if (*lcn != SPARSE_LCN || !new)
-                       return 0; /* Fast normal way without allocation. */
-               else if (clen > *len)
-                       clen = *len;
-       }
+       if (*len && (*lcn != SPARSE_LCN || !new))
+               return 0; /* Fast normal way without allocation. */
 
        /* No cluster in cache or we need to allocate cluster in hole. */
        sbi = ni->mi.sbi;
@@ -918,6 +914,17 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
        ni_lock(ni);
        down_write(&ni->file.run_lock);
 
+       /* Repeat the code above (under write lock). */
+       if (!run_lookup_entry(run, vcn, lcn, len, NULL))
+               *len = 0;
+
+       if (*len) {
+               if (*lcn != SPARSE_LCN || !new)
+                       goto out; /* normal way without allocation. */
+               if (clen > *len)
+                       clen = *len;
+       }
+
        le_b = NULL;
        attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b);
        if (!attr_b) {
@@ -1736,8 +1743,10 @@ repack:
                        le_b = NULL;
                        attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL,
                                              0, NULL, &mi_b);
-                       if (!attr_b)
-                               return -ENOENT;
+                       if (!attr_b) {
+                               err = -ENOENT;
+                               goto out;
+                       }
 
                        attr = attr_b;
                        le = le_b;
@@ -1818,13 +1827,15 @@ ins_ext:
 ok:
        run_truncate_around(run, vcn);
 out:
-       if (new_valid > data_size)
-               new_valid = data_size;
+       if (attr_b) {
+               if (new_valid > data_size)
+                       new_valid = data_size;
 
-       valid_size = le64_to_cpu(attr_b->nres.valid_size);
-       if (new_valid != valid_size) {
-               attr_b->nres.valid_size = cpu_to_le64(valid_size);
-               mi_b->dirty = true;
+               valid_size = le64_to_cpu(attr_b->nres.valid_size);
+               if (new_valid != valid_size) {
+                       attr_b->nres.valid_size = cpu_to_le64(valid_size);
+                       mi_b->dirty = true;
+               }
        }
 
        return err;
@@ -2073,7 +2084,7 @@ next_attr:
 
        /* Update inode size. */
        ni->i_valid = valid_size;
-       ni->vfs_inode.i_size = data_size;
+       i_size_write(&ni->vfs_inode, data_size);
        inode_set_bytes(&ni->vfs_inode, total_size);
        ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
        mark_inode_dirty(&ni->vfs_inode);
@@ -2488,7 +2499,7 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
        mi_b->dirty = true;
 
 done:
-       ni->vfs_inode.i_size += bytes;
+       i_size_write(&ni->vfs_inode, ni->vfs_inode.i_size + bytes);
        ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
        mark_inode_dirty(&ni->vfs_inode);
 
index 7c01735d1219d858b46809147fa06dbcc6cafe4c..9f4bd8d260901ca4fd4db97aea3687459e4ebc1a 100644 (file)
@@ -29,7 +29,7 @@ static inline bool al_is_valid_le(const struct ntfs_inode *ni,
 void al_destroy(struct ntfs_inode *ni)
 {
        run_close(&ni->attr_list.run);
-       kfree(ni->attr_list.le);
+       kvfree(ni->attr_list.le);
        ni->attr_list.le = NULL;
        ni->attr_list.size = 0;
        ni->attr_list.dirty = false;
@@ -127,12 +127,13 @@ struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni,
 {
        size_t off;
        u16 sz;
+       const unsigned le_min_size = le_size(0);
 
        if (!le) {
                le = ni->attr_list.le;
        } else {
                sz = le16_to_cpu(le->size);
-               if (sz < sizeof(struct ATTR_LIST_ENTRY)) {
+               if (sz < le_min_size) {
                        /* Impossible 'cause we should not return such le. */
                        return NULL;
                }
@@ -141,7 +142,7 @@ struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni,
 
        /* Check boundary. */
        off = PtrOffset(ni->attr_list.le, le);
-       if (off + sizeof(struct ATTR_LIST_ENTRY) > ni->attr_list.size) {
+       if (off + le_min_size > ni->attr_list.size) {
                /* The regular end of list. */
                return NULL;
        }
@@ -149,8 +150,7 @@ struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni,
        sz = le16_to_cpu(le->size);
 
        /* Check le for errors. */
-       if (sz < sizeof(struct ATTR_LIST_ENTRY) ||
-           off + sz > ni->attr_list.size ||
+       if (sz < le_min_size || off + sz > ni->attr_list.size ||
            sz < le->name_off + le->name_len * sizeof(short)) {
                return NULL;
        }
@@ -318,7 +318,7 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
                memcpy(ptr, al->le, off);
                memcpy(Add2Ptr(ptr, off + sz), le, old_size - off);
                le = Add2Ptr(ptr, off);
-               kfree(al->le);
+               kvfree(al->le);
                al->le = ptr;
        } else {
                memmove(Add2Ptr(le, sz), le, old_size - off);
index 63f14a0232f6a0e0672c5373748bf77b72931bf2..845f9b22deef0f42cabfb4156d4d8fe05c31fce9 100644 (file)
@@ -124,7 +124,7 @@ void wnd_close(struct wnd_bitmap *wnd)
 {
        struct rb_node *node, *next;
 
-       kfree(wnd->free_bits);
+       kvfree(wnd->free_bits);
        wnd->free_bits = NULL;
        run_close(&wnd->run);
 
@@ -1360,7 +1360,7 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits)
                memcpy(new_free, wnd->free_bits, wnd->nwnd * sizeof(short));
                memset(new_free + wnd->nwnd, 0,
                       (new_wnd - wnd->nwnd) * sizeof(short));
-               kfree(wnd->free_bits);
+               kvfree(wnd->free_bits);
                wnd->free_bits = new_free;
        }
 
index ec0566b322d5d0b4b36533a3a218671bb0ff7b02..5cf3d9decf646b1935517e8b564d807626e60e0f 100644 (file)
@@ -309,11 +309,31 @@ static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni,
                return 0;
        }
 
-       /* NTFS: symlinks are "dir + reparse" or "file + reparse" */
-       if (fname->dup.fa & FILE_ATTRIBUTE_REPARSE_POINT)
-               dt_type = DT_LNK;
-       else
-               dt_type = (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG;
+       /*
+        * NTFS: symlinks are "dir + reparse" or "file + reparse"
+        * Unfortunately reparse attribute is used for many purposes (several dozens).
+        * It is not possible here to know is this name symlink or not.
+        * To get exactly the type of name we should to open inode (read mft).
+        * getattr for opened file (fstat) correctly returns symlink.
+        */
+       dt_type = (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG;
+
+       /*
+        * It is not reliable to detect the type of name using duplicated information
+        * stored in parent directory.
+        * The only correct way to get the type of name - read MFT record and find ATTR_STD.
+        * The code below is not good idea.
+        * It does additional locks/reads just to get the type of name.
+        * Should we use additional mount option to enable branch below?
+        */
+       if ((fname->dup.fa & FILE_ATTRIBUTE_REPARSE_POINT) &&
+           ino != ni->mi.rno) {
+               struct inode *inode = ntfs_iget5(sbi->sb, &e->ref, NULL);
+               if (!IS_ERR_OR_NULL(inode)) {
+                       dt_type = fs_umode_to_dtype(inode->i_mode);
+                       iput(inode);
+               }
+       }
 
        return !dir_emit(ctx, (s8 *)name, name_len, ino, dt_type);
 }
@@ -495,11 +515,9 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs,
        struct INDEX_HDR *hdr;
        const struct ATTR_FILE_NAME *fname;
        u32 e_size, off, end;
-       u64 vbo = 0;
        size_t drs = 0, fles = 0, bit = 0;
-       loff_t i_size = ni->vfs_inode.i_size;
        struct indx_node *node = NULL;
-       u8 index_bits = ni->dir.index_bits;
+       size_t max_indx = i_size_read(&ni->vfs_inode) >> ni->dir.index_bits;
 
        if (is_empty)
                *is_empty = true;
@@ -518,8 +536,10 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs,
                        e = Add2Ptr(hdr, off);
                        e_size = le16_to_cpu(e->size);
                        if (e_size < sizeof(struct NTFS_DE) ||
-                           off + e_size > end)
+                           off + e_size > end) {
+                               /* Looks like corruption. */
                                break;
+                       }
 
                        if (de_is_last(e))
                                break;
@@ -543,7 +563,7 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs,
                                fles += 1;
                }
 
-               if (vbo >= i_size)
+               if (bit >= max_indx)
                        goto out;
 
                err = indx_used_bit(&ni->dir, ni, &bit);
@@ -553,8 +573,7 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs,
                if (bit == MINUS_ONE_T)
                        goto out;
 
-               vbo = (u64)bit << index_bits;
-               if (vbo >= i_size)
+               if (bit >= max_indx)
                        goto out;
 
                err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits,
@@ -564,7 +583,6 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs,
 
                hdr = &node->index->ihdr;
                bit += 1;
-               vbo = (u64)bit << ni->dir.idx2vbn_bits;
        }
 
 out:
@@ -593,5 +611,9 @@ const struct file_operations ntfs_dir_operations = {
        .iterate_shared = ntfs_readdir,
        .fsync          = generic_file_fsync,
        .open           = ntfs_file_open,
+       .unlocked_ioctl = ntfs_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ntfs_compat_ioctl,
+#endif
 };
 // clang-format on
index a5a30a24ce5dfa70d670826d1b5ac16a668d06be..5418662c80d8878afe72a8b8e8ffc43cc834b176 100644 (file)
@@ -48,7 +48,7 @@ static int ntfs_ioctl_fitrim(struct ntfs_sb_info *sbi, unsigned long arg)
        return 0;
 }
 
-static long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg)
+long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
        struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
@@ -61,7 +61,7 @@ static long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg)
 }
 
 #ifdef CONFIG_COMPAT
-static long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg)
+long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg)
 
 {
        return ntfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
@@ -188,6 +188,7 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
        u32 bh_next, bh_off, to;
        sector_t iblock;
        struct folio *folio;
+       bool dirty = false;
 
        for (; idx < idx_end; idx += 1, from = 0) {
                page_off = (loff_t)idx << PAGE_SHIFT;
@@ -223,29 +224,27 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
                        /* Ok, it's mapped. Make sure it's up-to-date. */
                        if (folio_test_uptodate(folio))
                                set_buffer_uptodate(bh);
-
-                       if (!buffer_uptodate(bh)) {
-                               err = bh_read(bh, 0);
-                               if (err < 0) {
-                                       folio_unlock(folio);
-                                       folio_put(folio);
-                                       goto out;
-                               }
+                       else if (bh_read(bh, 0) < 0) {
+                               err = -EIO;
+                               folio_unlock(folio);
+                               folio_put(folio);
+                               goto out;
                        }
 
                        mark_buffer_dirty(bh);
-
                } while (bh_off = bh_next, iblock += 1,
                         head != (bh = bh->b_this_page));
 
                folio_zero_segment(folio, from, to);
+               dirty = true;
 
                folio_unlock(folio);
                folio_put(folio);
                cond_resched();
        }
 out:
-       mark_inode_dirty(inode);
+       if (dirty)
+               mark_inode_dirty(inode);
        return err;
 }
 
@@ -261,6 +260,9 @@ static int ntfs_file_mmap(struct file *file, struct vm_area_struct *vma)
        bool rw = vma->vm_flags & VM_WRITE;
        int err;
 
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
        if (is_encrypted(ni)) {
                ntfs_inode_warn(inode, "mmap encrypted not supported");
                return -EOPNOTSUPP;
@@ -499,10 +501,14 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
                ni_lock(ni);
                err = attr_punch_hole(ni, vbo, len, &frame_size);
                ni_unlock(ni);
+               if (!err)
+                       goto ok;
+
                if (err != E_NTFS_NOTALIGNED)
                        goto out;
 
                /* Process not aligned punch. */
+               err = 0;
                mask = frame_size - 1;
                vbo_a = (vbo + mask) & ~mask;
                end_a = end & ~mask;
@@ -525,6 +531,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
                        ni_lock(ni);
                        err = attr_punch_hole(ni, vbo_a, end_a - vbo_a, NULL);
                        ni_unlock(ni);
+                       if (err)
+                               goto out;
                }
        } else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
                /*
@@ -564,6 +572,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
                ni_lock(ni);
                err = attr_insert_range(ni, vbo, len);
                ni_unlock(ni);
+               if (err)
+                       goto out;
        } else {
                /* Check new size. */
                u8 cluster_bits = sbi->cluster_bits;
@@ -633,11 +643,18 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
                                            &ni->file.run, i_size, &ni->i_valid,
                                            true, NULL);
                        ni_unlock(ni);
+                       if (err)
+                               goto out;
                } else if (new_size > i_size) {
-                       inode->i_size = new_size;
+                       i_size_write(inode, new_size);
                }
        }
 
+ok:
+       err = file_modified(file);
+       if (err)
+               goto out;
+
 out:
        if (map_locked)
                filemap_invalidate_unlock(mapping);
@@ -663,6 +680,9 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
        umode_t mode = inode->i_mode;
        int err;
 
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
        err = setattr_prepare(idmap, dentry, attr);
        if (err)
                goto out;
@@ -676,7 +696,7 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
                        goto out;
                }
                inode_dio_wait(inode);
-               oldsize = inode->i_size;
+               oldsize = i_size_read(inode);
                newsize = attr->ia_size;
 
                if (newsize <= oldsize)
@@ -688,7 +708,7 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
                        goto out;
 
                ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
-               inode->i_size = newsize;
+               i_size_write(inode, newsize);
        }
 
        setattr_copy(idmap, inode, attr);
@@ -718,6 +738,9 @@ static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
        struct inode *inode = file->f_mapping->host;
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
        if (is_encrypted(ni)) {
                ntfs_inode_warn(inode, "encrypted i/o not supported");
                return -EOPNOTSUPP;
@@ -752,6 +775,9 @@ static ssize_t ntfs_file_splice_read(struct file *in, loff_t *ppos,
        struct inode *inode = in->f_mapping->host;
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
        if (is_encrypted(ni)) {
                ntfs_inode_warn(inode, "encrypted i/o not supported");
                return -EOPNOTSUPP;
@@ -821,7 +847,7 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
        size_t count = iov_iter_count(from);
        loff_t pos = iocb->ki_pos;
        struct inode *inode = file_inode(file);
-       loff_t i_size = inode->i_size;
+       loff_t i_size = i_size_read(inode);
        struct address_space *mapping = inode->i_mapping;
        struct ntfs_inode *ni = ntfs_i(inode);
        u64 valid = ni->i_valid;
@@ -1028,6 +1054,8 @@ out:
        iocb->ki_pos += written;
        if (iocb->ki_pos > ni->i_valid)
                ni->i_valid = iocb->ki_pos;
+       if (iocb->ki_pos > i_size)
+               i_size_write(inode, iocb->ki_pos);
 
        return written;
 }
@@ -1041,8 +1069,12 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct address_space *mapping = file->f_mapping;
        struct inode *inode = mapping->host;
        ssize_t ret;
+       int err;
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
        if (is_encrypted(ni)) {
                ntfs_inode_warn(inode, "encrypted i/o not supported");
                return -EOPNOTSUPP;
@@ -1068,6 +1100,12 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (ret <= 0)
                goto out;
 
+       err = file_modified(iocb->ki_filp);
+       if (err) {
+               ret = err;
+               goto out;
+       }
+
        if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) {
                /* Should never be here, see ntfs_file_open(). */
                ret = -EOPNOTSUPP;
@@ -1097,6 +1135,9 @@ int ntfs_file_open(struct inode *inode, struct file *file)
 {
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
        if (unlikely((is_compressed(ni) || is_encrypted(ni)) &&
                     (file->f_flags & O_DIRECT))) {
                return -EOPNOTSUPP;
@@ -1138,7 +1179,8 @@ static int ntfs_file_release(struct inode *inode, struct file *file)
                down_write(&ni->file.run_lock);
 
                err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run,
-                                   inode->i_size, &ni->i_valid, false, NULL);
+                                   i_size_read(inode), &ni->i_valid, false,
+                                   NULL);
 
                up_write(&ni->file.run_lock);
                ni_unlock(ni);
index 3df2d9e34b9144f4b039ccc6197c9aa249b7ac64..3b42938a9d3b229b0bbf1eef9a80f83da5111113 100644 (file)
@@ -778,7 +778,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
        run_deallocate(sbi, &ni->attr_list.run, true);
        run_close(&ni->attr_list.run);
        ni->attr_list.size = 0;
-       kfree(ni->attr_list.le);
+       kvfree(ni->attr_list.le);
        ni->attr_list.le = NULL;
        ni->attr_list.dirty = false;
 
@@ -927,7 +927,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)
        return 0;
 
 out:
-       kfree(ni->attr_list.le);
+       kvfree(ni->attr_list.le);
        ni->attr_list.le = NULL;
        ni->attr_list.size = 0;
        return err;
@@ -2099,7 +2099,7 @@ int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page)
        gfp_t gfp_mask;
        struct page *pg;
 
-       if (vbo >= ni->vfs_inode.i_size) {
+       if (vbo >= i_size_read(&ni->vfs_inode)) {
                SetPageUptodate(page);
                err = 0;
                goto out;
@@ -2173,7 +2173,7 @@ int ni_decompress_file(struct ntfs_inode *ni)
 {
        struct ntfs_sb_info *sbi = ni->mi.sbi;
        struct inode *inode = &ni->vfs_inode;
-       loff_t i_size = inode->i_size;
+       loff_t i_size = i_size_read(inode);
        struct address_space *mapping = inode->i_mapping;
        gfp_t gfp_mask = mapping_gfp_mask(mapping);
        struct page **pages = NULL;
@@ -2457,6 +2457,7 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
        struct ATTR_LIST_ENTRY *le = NULL;
        struct runs_tree *run = &ni->file.run;
        u64 valid_size = ni->i_valid;
+       loff_t i_size = i_size_read(&ni->vfs_inode);
        u64 vbo_disk;
        size_t unc_size;
        u32 frame_size, i, npages_disk, ondisk_size;
@@ -2548,7 +2549,7 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
                        }
                }
 
-               frames = (ni->vfs_inode.i_size - 1) >> frame_bits;
+               frames = (i_size - 1) >> frame_bits;
 
                err = attr_wof_frame_info(ni, attr, run, frame64, frames,
                                          frame_bits, &ondisk_size, &vbo_data);
@@ -2556,8 +2557,7 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
                        goto out2;
 
                if (frame64 == frames) {
-                       unc_size = 1 + ((ni->vfs_inode.i_size - 1) &
-                                       (frame_size - 1));
+                       unc_size = 1 + ((i_size - 1) & (frame_size - 1));
                        ondisk_size = attr_size(attr) - vbo_data;
                } else {
                        unc_size = frame_size;
@@ -3259,6 +3259,9 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint)
        if (is_bad_inode(inode) || sb_rdonly(sb))
                return 0;
 
+       if (unlikely(ntfs3_forced_shutdown(sb)))
+               return -EIO;
+
        if (!ni_trylock(ni)) {
                /* 'ni' is under modification, skip for now. */
                mark_inode_dirty_sync(inode);
@@ -3288,7 +3291,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint)
                        modified = true;
                }
 
-               ts = inode_get_mtime(inode);
+               ts = inode_get_ctime(inode);
                dup.c_time = kernel2nt(&ts);
                if (std->c_time != dup.c_time) {
                        std->c_time = dup.c_time;
index 98ccb66508583138ed7f5c273b2f4450be88159b..855519713bf79074ed336ca7094cca5d5cdbc009 100644 (file)
@@ -465,7 +465,7 @@ static inline bool is_rst_area_valid(const struct RESTART_HDR *rhdr)
 {
        const struct RESTART_AREA *ra;
        u16 cl, fl, ul;
-       u32 off, l_size, file_dat_bits, file_size_round;
+       u32 off, l_size, seq_bits;
        u16 ro = le16_to_cpu(rhdr->ra_off);
        u32 sys_page = le32_to_cpu(rhdr->sys_page_size);
 
@@ -511,13 +511,15 @@ static inline bool is_rst_area_valid(const struct RESTART_HDR *rhdr)
        /* Make sure the sequence number bits match the log file size. */
        l_size = le64_to_cpu(ra->l_size);
 
-       file_dat_bits = sizeof(u64) * 8 - le32_to_cpu(ra->seq_num_bits);
-       file_size_round = 1u << (file_dat_bits + 3);
-       if (file_size_round != l_size &&
-           (file_size_round < l_size || (file_size_round / 2) > l_size)) {
-               return false;
+       seq_bits = sizeof(u64) * 8 + 3;
+       while (l_size) {
+               l_size >>= 1;
+               seq_bits -= 1;
        }
 
+       if (seq_bits != ra->seq_num_bits)
+               return false;
+
        /* The log page data offset and record header length must be quad-aligned. */
        if (!IS_ALIGNED(le16_to_cpu(ra->data_off), 8) ||
            !IS_ALIGNED(le16_to_cpu(ra->rec_hdr_len), 8))
@@ -974,6 +976,16 @@ skip_looking:
        return e;
 }
 
+struct restart_info {
+       u64 last_lsn;
+       struct RESTART_HDR *r_page;
+       u32 vbo;
+       bool chkdsk_was_run;
+       bool valid_page;
+       bool initialized;
+       bool restart;
+};
+
 #define RESTART_SINGLE_PAGE_IO cpu_to_le16(0x0001)
 
 #define NTFSLOG_WRAPPED 0x00000001
@@ -987,6 +999,7 @@ struct ntfs_log {
        struct ntfs_inode *ni;
 
        u32 l_size;
+       u32 orig_file_size;
        u32 sys_page_size;
        u32 sys_page_mask;
        u32 page_size;
@@ -1040,6 +1053,8 @@ struct ntfs_log {
 
        struct CLIENT_ID client_id;
        u32 client_undo_commit;
+
+       struct restart_info rst_info, rst_info2;
 };
 
 static inline u32 lsn_to_vbo(struct ntfs_log *log, const u64 lsn)
@@ -1105,16 +1120,6 @@ static inline bool verify_client_lsn(struct ntfs_log *log,
               lsn <= le64_to_cpu(log->ra->current_lsn) && lsn;
 }
 
-struct restart_info {
-       u64 last_lsn;
-       struct RESTART_HDR *r_page;
-       u32 vbo;
-       bool chkdsk_was_run;
-       bool valid_page;
-       bool initialized;
-       bool restart;
-};
-
 static int read_log_page(struct ntfs_log *log, u32 vbo,
                         struct RECORD_PAGE_HDR **buffer, bool *usa_error)
 {
@@ -1176,7 +1181,7 @@ out:
  * restart page header. It will stop the first time we find a
  * valid page header.
  */
-static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first,
+static int log_read_rst(struct ntfs_log *log, bool first,
                        struct restart_info *info)
 {
        u32 skip, vbo;
@@ -1192,7 +1197,7 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first,
        }
 
        /* Loop continuously until we succeed. */
-       for (; vbo < l_size; vbo = 2 * vbo + skip, skip = 0) {
+       for (; vbo < log->l_size; vbo = 2 * vbo + skip, skip = 0) {
                bool usa_error;
                bool brst, bchk;
                struct RESTART_AREA *ra;
@@ -1285,22 +1290,17 @@ check_result:
 /*
  * Ilog_init_pg_hdr - Init @log from restart page header.
  */
-static void log_init_pg_hdr(struct ntfs_log *log, u32 sys_page_size,
-                           u32 page_size, u16 major_ver, u16 minor_ver)
+static void log_init_pg_hdr(struct ntfs_log *log, u16 major_ver, u16 minor_ver)
 {
-       log->sys_page_size = sys_page_size;
-       log->sys_page_mask = sys_page_size - 1;
-       log->page_size = page_size;
-       log->page_mask = page_size - 1;
-       log->page_bits = blksize_bits(page_size);
+       log->sys_page_size = log->page_size;
+       log->sys_page_mask = log->page_mask;
 
        log->clst_per_page = log->page_size >> log->ni->mi.sbi->cluster_bits;
        if (!log->clst_per_page)
                log->clst_per_page = 1;
 
-       log->first_page = major_ver >= 2 ?
-                                 0x22 * page_size :
-                                 ((sys_page_size << 1) + (page_size << 1));
+       log->first_page = major_ver >= 2 ? 0x22 * log->page_size :
+                                          4 * log->page_size;
        log->major_ver = major_ver;
        log->minor_ver = minor_ver;
 }
@@ -1308,12 +1308,11 @@ static void log_init_pg_hdr(struct ntfs_log *log, u32 sys_page_size,
 /*
  * log_create - Init @log in cases when we don't have a restart area to use.
  */
-static void log_create(struct ntfs_log *log, u32 l_size, const u64 last_lsn,
+static void log_create(struct ntfs_log *log, const u64 last_lsn,
                       u32 open_log_count, bool wrapped, bool use_multi_page)
 {
-       log->l_size = l_size;
        /* All file offsets must be quadword aligned. */
-       log->file_data_bits = blksize_bits(l_size) - 3;
+       log->file_data_bits = blksize_bits(log->l_size) - 3;
        log->seq_num_mask = (8 << log->file_data_bits) - 1;
        log->seq_num_bits = sizeof(u64) * 8 - log->file_data_bits;
        log->seq_num = (last_lsn >> log->file_data_bits) + 2;
@@ -3720,10 +3719,8 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
        struct ntfs_sb_info *sbi = ni->mi.sbi;
        struct ntfs_log *log;
 
-       struct restart_info rst_info, rst_info2;
-       u64 rec_lsn, ra_lsn, checkpt_lsn = 0, rlsn = 0;
+       u64 rec_lsn, checkpt_lsn = 0, rlsn = 0;
        struct ATTR_NAME_ENTRY *attr_names = NULL;
-       struct ATTR_NAME_ENTRY *ane;
        struct RESTART_TABLE *dptbl = NULL;
        struct RESTART_TABLE *trtbl = NULL;
        const struct RESTART_TABLE *rt;
@@ -3741,9 +3738,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
        struct TRANSACTION_ENTRY *tr;
        struct DIR_PAGE_ENTRY *dp;
        u32 i, bytes_per_attr_entry;
-       u32 l_size = ni->vfs_inode.i_size;
-       u32 orig_file_size = l_size;
-       u32 page_size, vbo, tail, off, dlen;
+       u32 vbo, tail, off, dlen;
        u32 saved_len, rec_len, transact_id;
        bool use_second_page;
        struct RESTART_AREA *ra2, *ra = NULL;
@@ -3758,52 +3753,50 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
        u16 t16;
        u32 t32;
 
-       /* Get the size of page. NOTE: To replay we can use default page. */
-#if PAGE_SIZE >= DefaultLogPageSize && PAGE_SIZE <= DefaultLogPageSize * 2
-       page_size = norm_file_page(PAGE_SIZE, &l_size, true);
-#else
-       page_size = norm_file_page(PAGE_SIZE, &l_size, false);
-#endif
-       if (!page_size)
-               return -EINVAL;
-
        log = kzalloc(sizeof(struct ntfs_log), GFP_NOFS);
        if (!log)
                return -ENOMEM;
 
        log->ni = ni;
-       log->l_size = l_size;
-       log->one_page_buf = kmalloc(page_size, GFP_NOFS);
+       log->l_size = log->orig_file_size = ni->vfs_inode.i_size;
 
+       /* Get the size of page. NOTE: To replay we can use default page. */
+#if PAGE_SIZE >= DefaultLogPageSize && PAGE_SIZE <= DefaultLogPageSize * 2
+       log->page_size = norm_file_page(PAGE_SIZE, &log->l_size, true);
+#else
+       log->page_size = norm_file_page(PAGE_SIZE, &log->l_size, false);
+#endif
+       if (!log->page_size) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       log->one_page_buf = kmalloc(log->page_size, GFP_NOFS);
        if (!log->one_page_buf) {
                err = -ENOMEM;
                goto out;
        }
 
-       log->page_size = page_size;
-       log->page_mask = page_size - 1;
-       log->page_bits = blksize_bits(page_size);
+       log->page_mask = log->page_size - 1;
+       log->page_bits = blksize_bits(log->page_size);
 
        /* Look for a restart area on the disk. */
-       memset(&rst_info, 0, sizeof(struct restart_info));
-       err = log_read_rst(log, l_size, true, &rst_info);
+       err = log_read_rst(log, true, &log->rst_info);
        if (err)
                goto out;
 
        /* remember 'initialized' */
-       *initialized = rst_info.initialized;
+       *initialized = log->rst_info.initialized;
 
-       if (!rst_info.restart) {
-               if (rst_info.initialized) {
+       if (!log->rst_info.restart) {
+               if (log->rst_info.initialized) {
                        /* No restart area but the file is not initialized. */
                        err = -EINVAL;
                        goto out;
                }
 
-               log_init_pg_hdr(log, page_size, page_size, 1, 1);
-               log_create(log, l_size, 0, get_random_u32(), false, false);
-
-               log->ra = ra;
+               log_init_pg_hdr(log, 1, 1);
+               log_create(log, 0, get_random_u32(), false, false);
 
                ra = log_create_ra(log);
                if (!ra) {
@@ -3820,25 +3813,26 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
         * If the restart offset above wasn't zero then we won't
         * look for a second restart.
         */
-       if (rst_info.vbo)
+       if (log->rst_info.vbo)
                goto check_restart_area;
 
-       memset(&rst_info2, 0, sizeof(struct restart_info));
-       err = log_read_rst(log, l_size, false, &rst_info2);
+       err = log_read_rst(log, false, &log->rst_info2);
        if (err)
                goto out;
 
        /* Determine which restart area to use. */
-       if (!rst_info2.restart || rst_info2.last_lsn <= rst_info.last_lsn)
+       if (!log->rst_info2.restart ||
+           log->rst_info2.last_lsn <= log->rst_info.last_lsn)
                goto use_first_page;
 
        use_second_page = true;
 
-       if (rst_info.chkdsk_was_run && page_size != rst_info.vbo) {
+       if (log->rst_info.chkdsk_was_run &&
+           log->page_size != log->rst_info.vbo) {
                struct RECORD_PAGE_HDR *sp = NULL;
                bool usa_error;
 
-               if (!read_log_page(log, page_size, &sp, &usa_error) &&
+               if (!read_log_page(log, log->page_size, &sp, &usa_error) &&
                    sp->rhdr.sign == NTFS_CHKD_SIGNATURE) {
                        use_second_page = false;
                }
@@ -3846,52 +3840,43 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
        }
 
        if (use_second_page) {
-               kfree(rst_info.r_page);
-               memcpy(&rst_info, &rst_info2, sizeof(struct restart_info));
-               rst_info2.r_page = NULL;
+               kfree(log->rst_info.r_page);
+               memcpy(&log->rst_info, &log->rst_info2,
+                      sizeof(struct restart_info));
+               log->rst_info2.r_page = NULL;
        }
 
 use_first_page:
-       kfree(rst_info2.r_page);
+       kfree(log->rst_info2.r_page);
 
 check_restart_area:
        /*
         * If the restart area is at offset 0, we want
         * to write the second restart area first.
         */
-       log->init_ra = !!rst_info.vbo;
+       log->init_ra = !!log->rst_info.vbo;
 
        /* If we have a valid page then grab a pointer to the restart area. */
-       ra2 = rst_info.valid_page ?
-                     Add2Ptr(rst_info.r_page,
-                             le16_to_cpu(rst_info.r_page->ra_off)) :
+       ra2 = log->rst_info.valid_page ?
+                     Add2Ptr(log->rst_info.r_page,
+                             le16_to_cpu(log->rst_info.r_page->ra_off)) :
                      NULL;
 
-       if (rst_info.chkdsk_was_run ||
+       if (log->rst_info.chkdsk_was_run ||
            (ra2 && ra2->client_idx[1] == LFS_NO_CLIENT_LE)) {
                bool wrapped = false;
                bool use_multi_page = false;
                u32 open_log_count;
 
                /* Do some checks based on whether we have a valid log page. */
-               if (!rst_info.valid_page) {
-                       open_log_count = get_random_u32();
-                       goto init_log_instance;
-               }
-               open_log_count = le32_to_cpu(ra2->open_log_count);
-
-               /*
-                * If the restart page size isn't changing then we want to
-                * check how much work we need to do.
-                */
-               if (page_size != le32_to_cpu(rst_info.r_page->sys_page_size))
-                       goto init_log_instance;
+               open_log_count = log->rst_info.valid_page ?
+                                        le32_to_cpu(ra2->open_log_count) :
+                                        get_random_u32();
 
-init_log_instance:
-               log_init_pg_hdr(log, page_size, page_size, 1, 1);
+               log_init_pg_hdr(log, 1, 1);
 
-               log_create(log, l_size, rst_info.last_lsn, open_log_count,
-                          wrapped, use_multi_page);
+               log_create(log, log->rst_info.last_lsn, open_log_count, wrapped,
+                          use_multi_page);
 
                ra = log_create_ra(log);
                if (!ra) {
@@ -3916,28 +3901,27 @@ init_log_instance:
         * use the log file. We must use the system page size instead of the
         * default size if there is not a clean shutdown.
         */
-       t32 = le32_to_cpu(rst_info.r_page->sys_page_size);
-       if (page_size != t32) {
-               l_size = orig_file_size;
-               page_size =
-                       norm_file_page(t32, &l_size, t32 == DefaultLogPageSize);
+       t32 = le32_to_cpu(log->rst_info.r_page->sys_page_size);
+       if (log->page_size != t32) {
+               log->l_size = log->orig_file_size;
+               log->page_size = norm_file_page(t32, &log->l_size,
+                                               t32 == DefaultLogPageSize);
        }
 
-       if (page_size != t32 ||
-           page_size != le32_to_cpu(rst_info.r_page->page_size)) {
+       if (log->page_size != t32 ||
+           log->page_size != le32_to_cpu(log->rst_info.r_page->page_size)) {
                err = -EINVAL;
                goto out;
        }
 
        /* If the file size has shrunk then we won't mount it. */
-       if (l_size < le64_to_cpu(ra2->l_size)) {
+       if (log->l_size < le64_to_cpu(ra2->l_size)) {
                err = -EINVAL;
                goto out;
        }
 
-       log_init_pg_hdr(log, page_size, page_size,
-                       le16_to_cpu(rst_info.r_page->major_ver),
-                       le16_to_cpu(rst_info.r_page->minor_ver));
+       log_init_pg_hdr(log, le16_to_cpu(log->rst_info.r_page->major_ver),
+                       le16_to_cpu(log->rst_info.r_page->minor_ver));
 
        log->l_size = le64_to_cpu(ra2->l_size);
        log->seq_num_bits = le32_to_cpu(ra2->seq_num_bits);
@@ -3945,7 +3929,7 @@ init_log_instance:
        log->seq_num_mask = (8 << log->file_data_bits) - 1;
        log->last_lsn = le64_to_cpu(ra2->current_lsn);
        log->seq_num = log->last_lsn >> log->file_data_bits;
-       log->ra_off = le16_to_cpu(rst_info.r_page->ra_off);
+       log->ra_off = le16_to_cpu(log->rst_info.r_page->ra_off);
        log->restart_size = log->sys_page_size - log->ra_off;
        log->record_header_len = le16_to_cpu(ra2->rec_hdr_len);
        log->ra_size = le16_to_cpu(ra2->ra_len);
@@ -4045,7 +4029,7 @@ find_oldest:
        log->current_avail = current_log_avail(log);
 
        /* Remember which restart area to write first. */
-       log->init_ra = rst_info.vbo;
+       log->init_ra = log->rst_info.vbo;
 
 process_log:
        /* 1.0, 1.1, 2.0 log->major_ver/minor_ver - short values. */
@@ -4105,7 +4089,7 @@ process_log:
        log->client_id.seq_num = cr->seq_num;
        log->client_id.client_idx = client;
 
-       err = read_rst_area(log, &rst, &ra_lsn);
+       err = read_rst_area(log, &rst, &checkpt_lsn);
        if (err)
                goto out;
 
@@ -4114,9 +4098,8 @@ process_log:
 
        bytes_per_attr_entry = !rst->major_ver ? 0x2C : 0x28;
 
-       checkpt_lsn = le64_to_cpu(rst->check_point_start);
-       if (!checkpt_lsn)
-               checkpt_lsn = ra_lsn;
+       if (rst->check_point_start)
+               checkpt_lsn = le64_to_cpu(rst->check_point_start);
 
        /* Allocate and Read the Transaction Table. */
        if (!rst->transact_table_len)
@@ -4330,23 +4313,20 @@ check_attr_table:
        lcb = NULL;
 
 check_attribute_names2:
-       if (!rst->attr_names_len)
-               goto trace_attribute_table;
-
-       ane = attr_names;
-       if (!oatbl)
-               goto trace_attribute_table;
-       while (ane->off) {
-               /* TODO: Clear table on exit! */
-               oe = Add2Ptr(oatbl, le16_to_cpu(ane->off));
-               t16 = le16_to_cpu(ane->name_bytes);
-               oe->name_len = t16 / sizeof(short);
-               oe->ptr = ane->name;
-               oe->is_attr_name = 2;
-               ane = Add2Ptr(ane, sizeof(struct ATTR_NAME_ENTRY) + t16);
-       }
-
-trace_attribute_table:
+       if (rst->attr_names_len && oatbl) {
+               struct ATTR_NAME_ENTRY *ane = attr_names;
+               while (ane->off) {
+                       /* TODO: Clear table on exit! */
+                       oe = Add2Ptr(oatbl, le16_to_cpu(ane->off));
+                       t16 = le16_to_cpu(ane->name_bytes);
+                       oe->name_len = t16 / sizeof(short);
+                       oe->ptr = ane->name;
+                       oe->is_attr_name = 2;
+                       ane = Add2Ptr(ane,
+                                     sizeof(struct ATTR_NAME_ENTRY) + t16);
+               }
+       }
+
        /*
         * If the checkpt_lsn is zero, then this is a freshly
         * formatted disk and we have no work to do.
@@ -5189,7 +5169,7 @@ out:
        kfree(oatbl);
        kfree(dptbl);
        kfree(attr_names);
-       kfree(rst_info.r_page);
+       kfree(log->rst_info.r_page);
 
        kfree(ra);
        kfree(log->one_page_buf);
index fbfe21dbb42597cdb25a6d809f7b396e37508046..ae2ef5c11868c360f1285feffae734b2974d0d5c 100644 (file)
@@ -853,7 +853,8 @@ void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait)
        /*
         * sb can be NULL here. In this case sbi->flags should be 0 too.
         */
-       if (!sb || !(sbi->flags & NTFS_FLAGS_MFTMIRR))
+       if (!sb || !(sbi->flags & NTFS_FLAGS_MFTMIRR) ||
+           unlikely(ntfs3_forced_shutdown(sb)))
                return;
 
        blocksize = sb->s_blocksize;
@@ -1006,6 +1007,30 @@ static inline __le32 security_hash(const void *sd, size_t bytes)
        return cpu_to_le32(hash);
 }
 
+/*
+ * simple wrapper for sb_bread_unmovable.
+ */
+struct buffer_head *ntfs_bread(struct super_block *sb, sector_t block)
+{
+       struct ntfs_sb_info *sbi = sb->s_fs_info;
+       struct buffer_head *bh;
+
+       if (unlikely(block >= sbi->volume.blocks)) {
+               /* prevent generic message "attempt to access beyond end of device" */
+               ntfs_err(sb, "try to read out of volume at offset 0x%llx",
+                        (u64)block << sb->s_blocksize_bits);
+               return NULL;
+       }
+
+       bh = sb_bread_unmovable(sb, block);
+       if (bh)
+               return bh;
+
+       ntfs_err(sb, "failed to read volume at offset 0x%llx",
+                (u64)block << sb->s_blocksize_bits);
+       return NULL;
+}
+
 int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer)
 {
        struct block_device *bdev = sb->s_bdev;
@@ -2128,8 +2153,8 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi,
                        if (le32_to_cpu(d_security->size) == new_sec_size &&
                            d_security->key.hash == hash_key.hash &&
                            !memcmp(d_security + 1, sd, size_sd)) {
-                               *security_id = d_security->key.sec_id;
                                /* Such security already exists. */
+                               *security_id = d_security->key.sec_id;
                                err = 0;
                                goto out;
                        }
index cf92b2433f7a750aeb86383eb7440c730ad7dc95..daabaad63aaf64ae65b8d67bbd40de837bfe3486 100644 (file)
@@ -1462,7 +1462,7 @@ static int indx_create_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
                goto out2;
 
        if (in->name == I30_NAME) {
-               ni->vfs_inode.i_size = data_size;
+               i_size_write(&ni->vfs_inode, data_size);
                inode_set_bytes(&ni->vfs_inode, alloc_size);
        }
 
@@ -1544,7 +1544,7 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
        }
 
        if (in->name == I30_NAME)
-               ni->vfs_inode.i_size = data_size;
+               i_size_write(&ni->vfs_inode, data_size);
 
        *vbn = bit << indx->idx2vbn_bits;
 
@@ -2090,7 +2090,7 @@ static int indx_shrink(struct ntfs_index *indx, struct ntfs_inode *ni,
                return err;
 
        if (in->name == I30_NAME)
-               ni->vfs_inode.i_size = new_data;
+               i_size_write(&ni->vfs_inode, new_data);
 
        bpb = bitmap_size(bit);
        if (bpb * 8 == nbits)
@@ -2576,7 +2576,7 @@ int indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
                err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len,
                                    &indx->alloc_run, 0, NULL, false, NULL);
                if (in->name == I30_NAME)
-                       ni->vfs_inode.i_size = 0;
+                       i_size_write(&ni->vfs_inode, 0);
 
                err = ni_remove_attr(ni, ATTR_ALLOC, in->name, in->name_len,
                                     false, NULL);
index 5e3d713749185f116e145adea4b196fbd7be72d2..eb7a8c9fba0183f40096d673473be4dffaa7c4c8 100644 (file)
@@ -345,9 +345,7 @@ next_attr:
                        inode->i_size = le16_to_cpu(rp.SymbolicLinkReparseBuffer
                                                            .PrintNameLength) /
                                        sizeof(u16);
-
                        ni->i_valid = inode->i_size;
-
                        /* Clear directory bit. */
                        if (ni->ni_flags & NI_FLAG_DIR) {
                                indx_clear(&ni->dir);
@@ -412,7 +410,6 @@ end_enum:
                goto out;
 
        if (!is_match && name) {
-               /* Reuse rec as buffer for ascii name. */
                err = -ENOENT;
                goto out;
        }
@@ -427,6 +424,7 @@ end_enum:
 
        if (names != le16_to_cpu(rec->hard_links)) {
                /* Correct minor error on the fly. Do not mark inode as dirty. */
+               ntfs_inode_warn(inode, "Correct links count -> %u.", names);
                rec->hard_links = cpu_to_le16(names);
                ni->mi.dirty = true;
        }
@@ -653,9 +651,10 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo,
                        off = vbo & (PAGE_SIZE - 1);
                        folio_set_bh(bh, folio, off);
 
-                       err = bh_read(bh, 0);
-                       if (err < 0)
+                       if (bh_read(bh, 0) < 0) {
+                               err = -EIO;
                                goto out;
+                       }
                        folio_zero_segment(folio, off + voff, off + block_size);
                }
        }
@@ -853,9 +852,13 @@ static int ntfs_resident_writepage(struct folio *folio,
                                   struct writeback_control *wbc, void *data)
 {
        struct address_space *mapping = data;
-       struct ntfs_inode *ni = ntfs_i(mapping->host);
+       struct inode *inode = mapping->host;
+       struct ntfs_inode *ni = ntfs_i(inode);
        int ret;
 
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
        ni_lock(ni);
        ret = attr_data_write_resident(ni, &folio->page);
        ni_unlock(ni);
@@ -869,7 +872,12 @@ static int ntfs_resident_writepage(struct folio *folio,
 static int ntfs_writepages(struct address_space *mapping,
                           struct writeback_control *wbc)
 {
-       if (is_resident(ntfs_i(mapping->host)))
+       struct inode *inode = mapping->host;
+
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
+       if (is_resident(ntfs_i(inode)))
                return write_cache_pages(mapping, wbc, ntfs_resident_writepage,
                                         mapping);
        return mpage_writepages(mapping, wbc, ntfs_get_block);
@@ -889,6 +897,9 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping,
        struct inode *inode = mapping->host;
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
        *pagep = NULL;
        if (is_resident(ni)) {
                struct page *page =
@@ -974,7 +985,7 @@ int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos,
                }
 
                if (pos + err > inode->i_size) {
-                       inode->i_size = pos + err;
+                       i_size_write(inode, pos + err);
                        dirty = true;
                }
 
@@ -1306,6 +1317,11 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
                goto out1;
        }
 
+       if (unlikely(ntfs3_forced_shutdown(sb))) {
+               err = -EIO;
+               goto out2;
+       }
+
        /* Mark rw ntfs as dirty. it will be cleared at umount. */
        ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
 
index ee3093be51701e78d1e02f6f30a7b5a4019831a0..cae41db0aaa7d13e1fb4e0132b79261156a39306 100644 (file)
@@ -181,6 +181,9 @@ static int ntfs_unlink(struct inode *dir, struct dentry *dentry)
        struct ntfs_inode *ni = ntfs_i(dir);
        int err;
 
+       if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
+               return -EIO;
+
        ni_lock_dir(ni);
 
        err = ntfs_unlink_inode(dir, dentry);
@@ -199,6 +202,9 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
        u32 size = strlen(symname);
        struct inode *inode;
 
+       if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
+               return -EIO;
+
        inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFLNK | 0777, 0,
                                  symname, size, NULL);
 
@@ -227,6 +233,9 @@ static int ntfs_rmdir(struct inode *dir, struct dentry *dentry)
        struct ntfs_inode *ni = ntfs_i(dir);
        int err;
 
+       if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
+               return -EIO;
+
        ni_lock_dir(ni);
 
        err = ntfs_unlink_inode(dir, dentry);
@@ -264,6 +273,9 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir,
                      1024);
        static_assert(PATH_MAX >= 4 * 1024);
 
+       if (unlikely(ntfs3_forced_shutdown(sb)))
+               return -EIO;
+
        if (flags & ~RENAME_NOREPLACE)
                return -EINVAL;
 
index 86aecbb01a92f282ab621a26df9897b70b65df28..9c7478150a0352d4f46574b76e91ec27ce661cdb 100644 (file)
@@ -523,12 +523,10 @@ struct ATTR_LIST_ENTRY {
        __le64 vcn;             // 0x08: Starting VCN of this attribute.
        struct MFT_REF ref;     // 0x10: MFT record number with attribute.
        __le16 id;              // 0x18: struct ATTRIB ID.
-       __le16 name[3];         // 0x1A: Just to align. To get real name can use bNameOffset.
+       __le16 name[];          // 0x1A: To get real name use name_off.
 
 }; // sizeof(0x20)
 
-static_assert(sizeof(struct ATTR_LIST_ENTRY) == 0x20);
-
 static inline u32 le_size(u8 name_len)
 {
        return ALIGN(offsetof(struct ATTR_LIST_ENTRY, name) +
index f6706143d14bced3c2bfdbac59d4df1a8cb9da5e..79356fd29a14141de34ed006517b153fd9e4872b 100644 (file)
@@ -61,6 +61,8 @@ enum utf16_endian;
 
 /* sbi->flags */
 #define NTFS_FLAGS_NODISCARD           0x00000001
+/* ntfs in shutdown state. */
+#define NTFS_FLAGS_SHUTDOWN_BIT                0x00000002  /* == 4*/
 /* Set when LogFile is replaying. */
 #define NTFS_FLAGS_LOG_REPLAYING       0x00000008
 /* Set when we changed first MFT's which copy must be updated in $MftMirr. */
@@ -226,7 +228,7 @@ struct ntfs_sb_info {
        u64 maxbytes; // Maximum size for normal files.
        u64 maxbytes_sparse; // Maximum size for sparse file.
 
-       u32 flags; // See NTFS_FLAGS_XXX.
+       unsigned long flags; // See NTFS_FLAGS_
 
        CLST zone_max; // Maximum MFT zone length in clusters
        CLST bad_clusters; // The count of marked bad clusters.
@@ -473,7 +475,7 @@ bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn,
 int al_update(struct ntfs_inode *ni, int sync);
 static inline size_t al_aligned(size_t size)
 {
-       return (size + 1023) & ~(size_t)1023;
+       return size_add(size, 1023) & ~(size_t)1023;
 }
 
 /* Globals from bitfunc.c */
@@ -500,6 +502,8 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
 int ntfs_file_open(struct inode *inode, struct file *file);
 int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                __u64 start, __u64 len);
+long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg);
+long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg);
 extern const struct inode_operations ntfs_special_inode_operations;
 extern const struct inode_operations ntfs_file_inode_operations;
 extern const struct file_operations ntfs_file_operations;
@@ -584,6 +588,7 @@ bool check_index_header(const struct INDEX_HDR *hdr, size_t bytes);
 int log_replay(struct ntfs_inode *ni, bool *initialized);
 
 /* Globals from fsntfs.c */
+struct buffer_head *ntfs_bread(struct super_block *sb, sector_t block);
 bool ntfs_fix_pre_write(struct NTFS_RECORD_HEADER *rhdr, size_t bytes);
 int ntfs_fix_post_read(struct NTFS_RECORD_HEADER *rhdr, size_t bytes,
                       bool simple);
@@ -872,7 +877,7 @@ int ntfs_init_acl(struct mnt_idmap *idmap, struct inode *inode,
 
 int ntfs_acl_chmod(struct mnt_idmap *idmap, struct dentry *dentry);
 ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
-extern const struct xattr_handler * const ntfs_xattr_handlers[];
+extern const struct xattr_handler *const ntfs_xattr_handlers[];
 
 int ntfs_save_wsl_perm(struct inode *inode, __le16 *ea_size);
 void ntfs_get_wsl_perm(struct inode *inode);
@@ -999,6 +1004,11 @@ static inline struct ntfs_sb_info *ntfs_sb(struct super_block *sb)
        return sb->s_fs_info;
 }
 
+static inline int ntfs3_forced_shutdown(struct super_block *sb)
+{
+       return test_bit(NTFS_FLAGS_SHUTDOWN_BIT, &ntfs_sb(sb)->flags);
+}
+
 /*
  * ntfs_up_cluster - Align up on cluster boundary.
  */
@@ -1025,19 +1035,6 @@ static inline u64 bytes_to_block(const struct super_block *sb, u64 size)
        return (size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 }
 
-static inline struct buffer_head *ntfs_bread(struct super_block *sb,
-                                            sector_t block)
-{
-       struct buffer_head *bh = sb_bread(sb, block);
-
-       if (bh)
-               return bh;
-
-       ntfs_err(sb, "failed to read volume at offset 0x%llx",
-                (u64)block << sb->s_blocksize_bits);
-       return NULL;
-}
-
 static inline struct ntfs_inode *ntfs_i(struct inode *inode)
 {
        return container_of(inode, struct ntfs_inode, vfs_inode);
index 53629b1f65e995978cef9b312462447305cb578d..6aa3a9d44df1bdc90f56a947caf94c902590d983 100644 (file)
@@ -279,7 +279,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
                if (t16 > asize)
                        return NULL;
 
-               if (t16 + le32_to_cpu(attr->res.data_size) > asize)
+               if (le32_to_cpu(attr->res.data_size) > asize - t16)
                        return NULL;
 
                t32 = sizeof(short) * attr->name_len;
@@ -535,8 +535,20 @@ bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
                return false;
 
        if (ni && is_attr_indexed(attr)) {
-               le16_add_cpu(&ni->mi.mrec->hard_links, -1);
-               ni->mi.dirty = true;
+               u16 links = le16_to_cpu(ni->mi.mrec->hard_links);
+               struct ATTR_FILE_NAME *fname =
+                       attr->type != ATTR_NAME ?
+                               NULL :
+                               resident_data_ex(attr,
+                                                SIZEOF_ATTRIBUTE_FILENAME);
+               if (fname && fname->type == FILE_NAME_DOS) {
+                       /* Do not decrease links count deleting DOS name. */
+               } else if (!links) {
+                       /* minor error. Not critical. */
+               } else {
+                       ni->mi.mrec->hard_links = cpu_to_le16(links - 1);
+                       ni->mi.dirty = true;
+               }
        }
 
        used -= asize;
index 9153dffde950c2a396291bea88e3e6d31169f568..cef5467fd92833aec6fb0bce3879826c2a627a09 100644 (file)
@@ -122,13 +122,12 @@ void ntfs_inode_printk(struct inode *inode, const char *fmt, ...)
 
        if (name) {
                struct dentry *de = d_find_alias(inode);
-               const u32 name_len = ARRAY_SIZE(s_name_buf) - 1;
 
                if (de) {
                        spin_lock(&de->d_lock);
-                       snprintf(name, name_len, " \"%s\"", de->d_name.name);
+                       snprintf(name, sizeof(s_name_buf), " \"%s\"",
+                                de->d_name.name);
                        spin_unlock(&de->d_lock);
-                       name[name_len] = 0; /* To be sure. */
                } else {
                        name[0] = 0;
                }
@@ -625,7 +624,7 @@ static void ntfs3_free_sbi(struct ntfs_sb_info *sbi)
 {
        kfree(sbi->new_rec);
        kvfree(ntfs_put_shared(sbi->upcase));
-       kfree(sbi->def_table);
+       kvfree(sbi->def_table);
        kfree(sbi->compress.lznt);
 #ifdef CONFIG_NTFS3_LZX_XPRESS
        xpress_free_decompressor(sbi->compress.xpress);
@@ -714,6 +713,14 @@ static int ntfs_show_options(struct seq_file *m, struct dentry *root)
        return 0;
 }
 
+/*
+ * ntfs_shutdown - super_operations::shutdown
+ */
+static void ntfs_shutdown(struct super_block *sb)
+{
+       set_bit(NTFS_FLAGS_SHUTDOWN_BIT, &ntfs_sb(sb)->flags);
+}
+
 /*
  * ntfs_sync_fs - super_operations::sync_fs
  */
@@ -724,6 +731,9 @@ static int ntfs_sync_fs(struct super_block *sb, int wait)
        struct ntfs_inode *ni;
        struct inode *inode;
 
+       if (unlikely(ntfs3_forced_shutdown(sb)))
+               return -EIO;
+
        ni = sbi->security.ni;
        if (ni) {
                inode = &ni->vfs_inode;
@@ -763,6 +773,7 @@ static const struct super_operations ntfs_sops = {
        .put_super = ntfs_put_super,
        .statfs = ntfs_statfs,
        .show_options = ntfs_show_options,
+       .shutdown = ntfs_shutdown,
        .sync_fs = ntfs_sync_fs,
        .write_inode = ntfs3_write_inode,
 };
@@ -866,6 +877,7 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size,
        u16 fn, ao;
        u8 cluster_bits;
        u32 boot_off = 0;
+       sector_t boot_block = 0;
        const char *hint = "Primary boot";
 
        /* Save original dev_size. Used with alternative boot. */
@@ -873,11 +885,11 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size,
 
        sbi->volume.blocks = dev_size >> PAGE_SHIFT;
 
-       bh = ntfs_bread(sb, 0);
+read_boot:
+       bh = ntfs_bread(sb, boot_block);
        if (!bh)
-               return -EIO;
+               return boot_block ? -EINVAL : -EIO;
 
-check_boot:
        err = -EINVAL;
 
        /* Corrupted image; do not read OOB */
@@ -1108,26 +1120,24 @@ check_boot:
        }
 
 out:
-       if (err == -EINVAL && !bh->b_blocknr && dev_size0 > PAGE_SHIFT) {
+       brelse(bh);
+
+       if (err == -EINVAL && !boot_block && dev_size0 > PAGE_SHIFT) {
                u32 block_size = min_t(u32, sector_size, PAGE_SIZE);
                u64 lbo = dev_size0 - sizeof(*boot);
 
-               /*
-                * Try alternative boot (last sector)
-                */
-               brelse(bh);
-
-               sb_set_blocksize(sb, block_size);
-               bh = ntfs_bread(sb, lbo >> blksize_bits(block_size));
-               if (!bh)
-                       return -EINVAL;
-
+               boot_block = lbo >> blksize_bits(block_size);
                boot_off = lbo & (block_size - 1);
-               hint = "Alternative boot";
-               dev_size = dev_size0; /* restore original size. */
-               goto check_boot;
+               if (boot_block && block_size >= boot_off + sizeof(*boot)) {
+                       /*
+                        * Try alternative boot (last sector)
+                        */
+                       sb_set_blocksize(sb, block_size);
+                       hint = "Alternative boot";
+                       dev_size = dev_size0; /* restore original size. */
+                       goto read_boot;
+               }
        }
-       brelse(bh);
 
        return err;
 }
index 4274b6f31cfa1c49fec865fe0e1d81ab152e040b..53e7d1fa036aa6e50a3ccd529d88584b1350cd74 100644 (file)
@@ -219,6 +219,9 @@ static ssize_t ntfs_list_ea(struct ntfs_inode *ni, char *buffer,
                if (!ea->name_len)
                        break;
 
+               if (ea->name_len > ea_size)
+                       break;
+
                if (buffer) {
                        /* Check if we can use field ea->name */
                        if (off + ea_size > size)
@@ -744,6 +747,9 @@ static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de,
        int err;
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
+               return -EIO;
+
        /* Dispatch request. */
        if (!strcmp(name, SYSTEM_DOS_ATTRIB)) {
                /* system.dos_attrib */
index b8e25ca51016d9df648ca58495baa9db553330ec..8586e2f5d24390c91263ea1ee48e7c3b22199cd2 100644 (file)
@@ -265,20 +265,18 @@ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
        if (IS_ERR(old_file))
                return PTR_ERR(old_file);
 
+       /* Try to use clone_file_range to clone up within the same fs */
+       cloned = vfs_clone_file_range(old_file, 0, new_file, 0, len, 0);
+       if (cloned == len)
+               goto out_fput;
+
+       /* Couldn't clone, so now we try to copy the data */
        error = rw_verify_area(READ, old_file, &old_pos, len);
        if (!error)
                error = rw_verify_area(WRITE, new_file, &new_pos, len);
        if (error)
                goto out_fput;
 
-       /* Try to use clone_file_range to clone up within the same fs */
-       ovl_start_write(dentry);
-       cloned = do_clone_file_range(old_file, 0, new_file, 0, len, 0);
-       ovl_end_write(dentry);
-       if (cloned == len)
-               goto out_fput;
-       /* Couldn't clone, so now we try to copy the data */
-
        /* Check if lower fs supports seek operation */
        if (old_file->f_mode & FMODE_LSEEK)
                skip_hole = true;
index ff08a8957552add31a8fdf98e202f8380d519e50..34a47fb0c57f2570a4f7cb1f45373ddaf2afa883 100644 (file)
@@ -477,13 +477,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
        int permitted;
        struct mm_struct *mm;
        unsigned long long start_time;
-       unsigned long cmin_flt = 0, cmaj_flt = 0;
-       unsigned long  min_flt = 0,  maj_flt = 0;
-       u64 cutime, cstime, utime, stime;
-       u64 cgtime, gtime;
+       unsigned long cmin_flt, cmaj_flt, min_flt, maj_flt;
+       u64 cutime, cstime, cgtime, utime, stime, gtime;
        unsigned long rsslim = 0;
        unsigned long flags;
        int exit_code = task->exit_code;
+       struct signal_struct *sig = task->signal;
+       unsigned int seq = 1;
 
        state = *get_task_state(task);
        vsize = eip = esp = 0;
@@ -511,12 +511,8 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
 
        sigemptyset(&sigign);
        sigemptyset(&sigcatch);
-       cutime = cstime = utime = stime = 0;
-       cgtime = gtime = 0;
 
        if (lock_task_sighand(task, &flags)) {
-               struct signal_struct *sig = task->signal;
-
                if (sig->tty) {
                        struct pid *pgrp = tty_get_pgrp(sig->tty);
                        tty_pgrp = pid_nr_ns(pgrp, ns);
@@ -527,28 +523,9 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
                num_threads = get_nr_threads(task);
                collect_sigign_sigcatch(task, &sigign, &sigcatch);
 
-               cmin_flt = sig->cmin_flt;
-               cmaj_flt = sig->cmaj_flt;
-               cutime = sig->cutime;
-               cstime = sig->cstime;
-               cgtime = sig->cgtime;
                rsslim = READ_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
 
-               /* add up live thread stats at the group level */
                if (whole) {
-                       struct task_struct *t;
-
-                       __for_each_thread(sig, t) {
-                               min_flt += t->min_flt;
-                               maj_flt += t->maj_flt;
-                               gtime += task_gtime(t);
-                       }
-
-                       min_flt += sig->min_flt;
-                       maj_flt += sig->maj_flt;
-                       thread_group_cputime_adjusted(task, &utime, &stime);
-                       gtime += sig->gtime;
-
                        if (sig->flags & (SIGNAL_GROUP_EXIT | SIGNAL_STOP_STOPPED))
                                exit_code = sig->group_exit_code;
                }
@@ -562,10 +539,41 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
 
        if (permitted && (!whole || num_threads < 2))
                wchan = !task_is_running(task);
-       if (!whole) {
+
+       do {
+               seq++; /* 2 on the 1st/lockless path, otherwise odd */
+               flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
+
+               cmin_flt = sig->cmin_flt;
+               cmaj_flt = sig->cmaj_flt;
+               cutime = sig->cutime;
+               cstime = sig->cstime;
+               cgtime = sig->cgtime;
+
+               if (whole) {
+                       struct task_struct *t;
+
+                       min_flt = sig->min_flt;
+                       maj_flt = sig->maj_flt;
+                       gtime = sig->gtime;
+
+                       rcu_read_lock();
+                       __for_each_thread(sig, t) {
+                               min_flt += t->min_flt;
+                               maj_flt += t->maj_flt;
+                               gtime += task_gtime(t);
+                       }
+                       rcu_read_unlock();
+               }
+       } while (need_seqretry(&sig->stats_lock, seq));
+       done_seqretry_irqrestore(&sig->stats_lock, seq, flags);
+
+       if (whole) {
+               thread_group_cputime_adjusted(task, &utime, &stime);
+       } else {
+               task_cputime_adjusted(task, &utime, &stime);
                min_flt = task->min_flt;
                maj_flt = task->maj_flt;
-               task_cputime_adjusted(task, &utime, &stime);
                gtime = task_gtime(task);
        }
 
index f8c1120b8311f62324324b911b0aa4aebe4ccb04..de07f978ce3ebe16bf42bf5315996fd074de5aac 100644 (file)
@@ -373,9 +373,9 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
 }
 EXPORT_SYMBOL(generic_remap_file_range_prep);
 
-loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
-                          struct file *file_out, loff_t pos_out,
-                          loff_t len, unsigned int remap_flags)
+loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
+                           struct file *file_out, loff_t pos_out,
+                           loff_t len, unsigned int remap_flags)
 {
        loff_t ret;
 
@@ -391,23 +391,6 @@ loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
        if (!file_in->f_op->remap_file_range)
                return -EOPNOTSUPP;
 
-       ret = file_in->f_op->remap_file_range(file_in, pos_in,
-                       file_out, pos_out, len, remap_flags);
-       if (ret < 0)
-               return ret;
-
-       fsnotify_access(file_in);
-       fsnotify_modify(file_out);
-       return ret;
-}
-EXPORT_SYMBOL(do_clone_file_range);
-
-loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
-                           struct file *file_out, loff_t pos_out,
-                           loff_t len, unsigned int remap_flags)
-{
-       loff_t ret;
-
        ret = remap_verify_area(file_in, pos_in, len, false);
        if (ret)
                return ret;
@@ -417,10 +400,14 @@ loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
                return ret;
 
        file_start_write(file_out);
-       ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len,
-                                 remap_flags);
+       ret = file_in->f_op->remap_file_range(file_in, pos_in,
+                       file_out, pos_out, len, remap_flags);
        file_end_write(file_out);
+       if (ret < 0)
+               return ret;
 
+       fsnotify_access(file_in);
+       fsnotify_modify(file_out);
        return ret;
 }
 EXPORT_SYMBOL(vfs_clone_file_range);
index 1daeb5714faad14c24c49a5efd5d118aaf04b54c..3de5047a7ff988c2049350e464771e912b12894e 100644 (file)
@@ -242,6 +242,7 @@ replay_again:
                .desired_access =  FILE_READ_DATA | FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .fid = pfid,
+               .replay = !!(retries),
        };
 
        rc = SMB2_open_init(tcon, server,
index c86a72c9d9ecd4268481a4caa29e58004cb7d6b9..53c75cfb33ab9446740133e7f19da6229eeffd55 100644 (file)
@@ -1378,6 +1378,7 @@ struct cifs_open_parms {
        struct cifs_fid *fid;
        umode_t mode;
        bool reconnect:1;
+       bool replay:1; /* indicates that this open is for a replay */
 };
 
 struct cifs_fid {
index bfd568f8971056b2c9ffbd509e026f140549f1af..ac9595504f4b11fa066a6516f034bff8bc09d56b 100644 (file)
@@ -233,6 +233,12 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
        list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) {
                /* check if iface is still active */
                spin_lock(&ses->chan_lock);
+               if (cifs_ses_get_chan_index(ses, server) ==
+                   CIFS_INVAL_CHAN_INDEX) {
+                       spin_unlock(&ses->chan_lock);
+                       continue;
+               }
+
                if (!cifs_chan_is_iface_active(ses, server)) {
                        spin_unlock(&ses->chan_lock);
                        cifs_chan_update_iface(ses, server);
@@ -3438,8 +3444,18 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
         * the user on mount
         */
        if ((cifs_sb->ctx->wsize == 0) ||
-           (cifs_sb->ctx->wsize > server->ops->negotiate_wsize(tcon, ctx)))
-               cifs_sb->ctx->wsize = server->ops->negotiate_wsize(tcon, ctx);
+           (cifs_sb->ctx->wsize > server->ops->negotiate_wsize(tcon, ctx))) {
+               cifs_sb->ctx->wsize =
+                       round_down(server->ops->negotiate_wsize(tcon, ctx), PAGE_SIZE);
+               /*
+                * in the very unlikely event that the server sent a max write size under PAGE_SIZE,
+                * (which would get rounded down to 0) then reset wsize to absolute minimum eg 4096
+                */
+               if (cifs_sb->ctx->wsize == 0) {
+                       cifs_sb->ctx->wsize = PAGE_SIZE;
+                       cifs_dbg(VFS, "wsize too small, reset to minimum ie PAGE_SIZE, usually 4096\n");
+               }
+       }
        if ((cifs_sb->ctx->rsize == 0) ||
            (cifs_sb->ctx->rsize > server->ops->negotiate_rsize(tcon, ctx)))
                cifs_sb->ctx->rsize = server->ops->negotiate_rsize(tcon, ctx);
@@ -4228,6 +4244,11 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
 
        /* only send once per connect */
        spin_lock(&tcon->tc_lock);
+
+       /* if tcon is marked for needing reconnect, update state */
+       if (tcon->need_reconnect)
+               tcon->status = TID_NEED_TCON;
+
        if (tcon->status == TID_GOOD) {
                spin_unlock(&tcon->tc_lock);
                return 0;
index a8a1d386da6566a2dec94099ae08a80199462bae..449c59830039bc04897e5031dba2dbc9c6649bad 100644 (file)
@@ -565,6 +565,11 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
 
        /* only send once per connect */
        spin_lock(&tcon->tc_lock);
+
+       /* if tcon is marked for needing reconnect, update state */
+       if (tcon->need_reconnect)
+               tcon->status = TID_NEED_TCON;
+
        if (tcon->status == TID_GOOD) {
                spin_unlock(&tcon->tc_lock);
                return 0;
@@ -625,8 +630,8 @@ out:
                spin_lock(&tcon->tc_lock);
                if (tcon->status == TID_IN_TCON)
                        tcon->status = TID_GOOD;
-               spin_unlock(&tcon->tc_lock);
                tcon->need_reconnect = false;
+               spin_unlock(&tcon->tc_lock);
        }
 
        return rc;
index b75282c204dadff986f9711d38e775834c30ddd2..f391c9b803d84f9549b50a57f860abdaf58e43b2 100644 (file)
@@ -175,6 +175,9 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
 
        /* only send once per connect */
        spin_lock(&tcon->tc_lock);
+       if (tcon->need_reconnect)
+               tcon->status = TID_NEED_RECON;
+
        if (tcon->status != TID_NEED_RECON) {
                spin_unlock(&tcon->tc_lock);
                return;
index 52cbef2eeb28f6ba0013063b4bafcecc08c3a02d..4b2f5aa2ea0e1de026302b9e543e2e13429107f9 100644 (file)
@@ -211,7 +211,7 @@ cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_c
 
        switch (match_token(value, cifs_secflavor_tokens, args)) {
        case Opt_sec_krb5p:
-               cifs_errorf(fc, "sec=krb5p is not supported!\n");
+               cifs_errorf(fc, "sec=krb5p is not supported. Use sec=krb5,seal instead\n");
                return 1;
        case Opt_sec_krb5i:
                ctx->sign = true;
@@ -1111,6 +1111,17 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
        case Opt_wsize:
                ctx->wsize = result.uint_32;
                ctx->got_wsize = true;
+               if (ctx->wsize % PAGE_SIZE != 0) {
+                       ctx->wsize = round_down(ctx->wsize, PAGE_SIZE);
+                       if (ctx->wsize == 0) {
+                               ctx->wsize = PAGE_SIZE;
+                               cifs_dbg(VFS, "wsize too small, reset to minimum %ld\n", PAGE_SIZE);
+                       } else {
+                               cifs_dbg(VFS,
+                                        "wsize rounded down to %d to multiple of PAGE_SIZE %ld\n",
+                                        ctx->wsize, PAGE_SIZE);
+                       }
+               }
                break;
        case Opt_acregmax:
                ctx->acregmax = HZ * result.uint_32;
index a6968573b775e7bdcab3df948908e9494f792027..4a517b280f2b79a2c1395a1c627b496def7392a7 100644 (file)
@@ -168,6 +168,21 @@ static char *automount_fullpath(struct dentry *dentry, void *page)
        return s;
 }
 
+static void fs_context_set_ids(struct smb3_fs_context *ctx)
+{
+       kuid_t uid = current_fsuid();
+       kgid_t gid = current_fsgid();
+
+       if (ctx->multiuser) {
+               if (!ctx->uid_specified)
+                       ctx->linux_uid = uid;
+               if (!ctx->gid_specified)
+                       ctx->linux_gid = gid;
+       }
+       if (!ctx->cruid_specified)
+               ctx->cred_uid = uid;
+}
+
 /*
  * Create a vfsmount that we can automount
  */
@@ -205,6 +220,7 @@ static struct vfsmount *cifs_do_automount(struct path *path)
        tmp.leaf_fullpath = NULL;
        tmp.UNC = tmp.prepath = NULL;
        tmp.dfs_root_ses = NULL;
+       fs_context_set_ids(&tmp);
 
        rc = smb3_fs_context_dup(ctx, &tmp);
        if (rc) {
index 3b1b01d10f7d7a2f1d12b158ded96d58203f80d0..b520eea7bfce83b2fd8e9a1d9e1685c39516840e 100644 (file)
@@ -307,14 +307,16 @@ cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
 }
 
 static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr,
-                                      SEARCH_ID_FULL_DIR_INFO *info,
+                                      const void *info,
                                       struct cifs_sb_info *cifs_sb)
 {
+       const FILE_FULL_DIRECTORY_INFO *di = info;
+
        __dir_info_to_fattr(fattr, info);
 
-       /* See MS-FSCC 2.4.19 FileIdFullDirectoryInformation */
+       /* See MS-FSCC 2.4.14, 2.4.19 */
        if (fattr->cf_cifsattrs & ATTR_REPARSE)
-               fattr->cf_cifstag = le32_to_cpu(info->EaSize);
+               fattr->cf_cifstag = le32_to_cpu(di->EaSize);
        cifs_fill_common_info(fattr, cifs_sb);
 }
 
@@ -396,7 +398,7 @@ ffirst_retry:
        } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
                cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
        } else /* not srvinos - BB fixme add check for backlevel? */ {
-               cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
+               cifsFile->srch_inf.info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO;
        }
 
        search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
@@ -987,10 +989,9 @@ static int cifs_filldir(char *find_entry, struct file *file,
                                       (FIND_FILE_STANDARD_INFO *)find_entry,
                                       cifs_sb);
                break;
+       case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
        case SMB_FIND_FILE_ID_FULL_DIR_INFO:
-               cifs_fulldir_info_to_fattr(&fattr,
-                                          (SEARCH_ID_FULL_DIR_INFO *)find_entry,
-                                          cifs_sb);
+               cifs_fulldir_info_to_fattr(&fattr, find_entry, cifs_sb);
                break;
        default:
                cifs_dir_info_to_fattr(&fattr,
index ed4bd88dd528aab05c9594120116303ca35975e0..8f37373fd33344bacbf4d492f6115d9396573379 100644 (file)
@@ -76,7 +76,7 @@ cifs_ses_get_chan_index(struct cifs_ses *ses,
        unsigned int i;
 
        /* if the channel is waiting for termination */
-       if (server->terminate)
+       if (server && server->terminate)
                return CIFS_INVAL_CHAN_INDEX;
 
        for (i = 0; i < ses->chan_count; i++) {
@@ -88,7 +88,6 @@ cifs_ses_get_chan_index(struct cifs_ses *ses,
        if (server)
                cifs_dbg(VFS, "unable to get chan index for server: 0x%llx",
                         server->conn_id);
-       WARN_ON(1);
        return CIFS_INVAL_CHAN_INDEX;
 }
 
index 83c898afc8354bf04c7a86ee57e4343ad3618319..4695433fcf397f529754cc9ec266cb5ac1727512 100644 (file)
@@ -619,7 +619,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
                goto out;
        }
 
-       while (bytes_left >= sizeof(*p)) {
+       while (bytes_left >= (ssize_t)sizeof(*p)) {
                memset(&tmp_iface, 0, sizeof(tmp_iface));
                tmp_iface.speed = le64_to_cpu(p->LinkSpeed);
                tmp_iface.rdma_capable = le32_to_cpu(p->Capability & RDMA_CAPABLE) ? 1 : 0;
@@ -1204,6 +1204,7 @@ replay_again:
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
                .fid = &fid,
+               .replay = !!(retries),
        };
 
        rc = SMB2_open_init(tcon, server,
@@ -1569,6 +1570,7 @@ replay_again:
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, create_options),
                .fid = &fid,
+               .replay = !!(retries),
        };
 
        if (qi.flags & PASSTHRU_FSCTL) {
@@ -2295,6 +2297,7 @@ replay_again:
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
                .fid = fid,
+               .replay = !!(retries),
        };
 
        rc = SMB2_open_init(tcon, server,
@@ -2681,6 +2684,7 @@ replay_again:
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
                .fid = &fid,
+               .replay = !!(retries),
        };
 
        rc = SMB2_open_init(tcon, server,
@@ -5213,7 +5217,7 @@ static int smb2_create_reparse_symlink(const unsigned int xid,
        struct inode *new;
        struct kvec iov;
        __le16 *path;
-       char *sym;
+       char *sym, sep = CIFS_DIR_SEP(cifs_sb);
        u16 len, plen;
        int rc = 0;
 
@@ -5227,7 +5231,8 @@ static int smb2_create_reparse_symlink(const unsigned int xid,
                .symlink_target = sym,
        };
 
-       path = cifs_convert_path_to_utf16(symname, cifs_sb);
+       convert_delimiter(sym, sep);
+       path = cifs_convert_path_to_utf16(sym, cifs_sb);
        if (!path) {
                rc = -ENOMEM;
                goto out;
@@ -5250,7 +5255,10 @@ static int smb2_create_reparse_symlink(const unsigned int xid,
        buf->PrintNameLength = cpu_to_le16(plen);
        memcpy(buf->PathBuffer, path, plen);
        buf->Flags = cpu_to_le32(*symname != '/' ? SYMLINK_FLAG_RELATIVE : 0);
+       if (*sym != sep)
+               buf->Flags = cpu_to_le32(SYMLINK_FLAG_RELATIVE);
 
+       convert_delimiter(sym, '/');
        iov.iov_base = buf;
        iov.iov_len = len;
        new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
index c58fa44dd6b06aa76abad19cb432a6ed6f81e13b..608ee05491e262c5cf4555c6b51b364cdc60a03b 100644 (file)
@@ -2404,8 +2404,13 @@ create_durable_v2_buf(struct cifs_open_parms *oparms)
         */
        buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
        buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
-       generate_random_uuid(buf->dcontext.CreateGuid);
-       memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
+
+       /* for replay, we should not overwrite the existing create guid */
+       if (!oparms->replay) {
+               generate_random_uuid(buf->dcontext.CreateGuid);
+               memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
+       } else
+               memcpy(buf->dcontext.CreateGuid, pfid->create_guid, 16);
 
        /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
        buf->Name[0] = 'D';
@@ -3142,6 +3147,7 @@ replay_again:
        /* reinitialize for possible replay */
        flags = 0;
        server = cifs_pick_channel(ses);
+       oparms->replay = !!(retries);
 
        cifs_dbg(FYI, "create/open\n");
        if (!ses || !server)
@@ -5206,6 +5212,9 @@ int SMB2_query_directory_init(const unsigned int xid,
        case SMB_FIND_FILE_POSIX_INFO:
                req->FileInformationClass = SMB_FIND_FILE_POSIX_INFO;
                break;
+       case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+               req->FileInformationClass = FILE_FULL_DIRECTORY_INFORMATION;
+               break;
        default:
                cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
                        info_level);
@@ -5275,6 +5284,9 @@ smb2_parse_query_directory(struct cifs_tcon *tcon,
                /* note that posix payload are variable size */
                info_buf_size = sizeof(struct smb2_posix_info);
                break;
+       case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+               info_buf_size = sizeof(FILE_FULL_DIRECTORY_INFO);
+               break;
        default:
                cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
                         srch_inf->info_level);
index 9e8afaa686e3aa8c12e908348aa38b34168ec367..1a5faa6f6e7bc3ddb96bdaa1ce953ba06f3bf5a2 100644 (file)
@@ -261,6 +261,7 @@ out_ascii:
 
 /**
  * ksmbd_extract_sharename() - get share name from tree connect request
+ * @um: pointer to a unicode_map structure for character encoding handling
  * @treename:  buffer containing tree name and share name
  *
  * Return:      share name on success, otherwise error
index ba7a72a6a4f45f6b756768c4a3a48e19d74e3683..0c97d3c860726a303081eb25927d38439bfaf4ea 100644 (file)
@@ -6173,8 +6173,10 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
                err = ksmbd_iov_pin_rsp_read(work, (void *)rsp,
                                             offsetof(struct smb2_read_rsp, Buffer),
                                             aux_payload_buf, nbytes);
-               if (err)
+               if (err) {
+                       kvfree(aux_payload_buf);
                        goto out;
+               }
                kvfree(rpc_resp);
        } else {
                err = ksmbd_iov_pin_rsp(work, (void *)rsp,
@@ -6384,8 +6386,10 @@ int smb2_read(struct ksmbd_work *work)
        err = ksmbd_iov_pin_rsp_read(work, (void *)rsp,
                                     offsetof(struct smb2_read_rsp, Buffer),
                                     aux_payload_buf, nbytes);
-       if (err)
+       if (err) {
+               kvfree(aux_payload_buf);
                goto out;
+       }
        ksmbd_fd_put(work, fp);
        return 0;
 
index 6ab2318a9c8e80271a3f17d2ad852dacad2f2fa1..dba5dcb62bef5d3788c21fbffa11ebfbe4988b0c 100644 (file)
@@ -348,7 +348,12 @@ static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
        struct zonefs_inode_info *zi = ZONEFS_I(inode);
 
        if (error) {
-               zonefs_io_error(inode, true);
+               /*
+                * For Sync IOs, error recovery is called from
+                * zonefs_file_dio_write().
+                */
+               if (!is_sync_kiocb(iocb))
+                       zonefs_io_error(inode, true);
                return error;
        }
 
@@ -491,6 +496,14 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
                        ret = -EINVAL;
                        goto inode_unlock;
                }
+               /*
+                * Advance the zone write pointer offset. This assumes that the
+                * IO will succeed, which is OK to do because we do not allow
+                * partial writes (IOMAP_DIO_PARTIAL is not set) and if the IO
+                * fails, the error path will correct the write pointer offset.
+                */
+               z->z_wpoffset += count;
+               zonefs_inode_account_active(inode);
                mutex_unlock(&zi->i_truncate_mutex);
        }
 
@@ -504,20 +517,19 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
        if (ret == -ENOTBLK)
                ret = -EBUSY;
 
-       if (zonefs_zone_is_seq(z) &&
-           (ret > 0 || ret == -EIOCBQUEUED)) {
-               if (ret > 0)
-                       count = ret;
-
-               /*
-                * Update the zone write pointer offset assuming the write
-                * operation succeeded. If it did not, the error recovery path
-                * will correct it. Also do active seq file accounting.
-                */
-               mutex_lock(&zi->i_truncate_mutex);
-               z->z_wpoffset += count;
-               zonefs_inode_account_active(inode);
-               mutex_unlock(&zi->i_truncate_mutex);
+       /*
+        * For a failed IO or partial completion, trigger error recovery
+        * to update the zone write pointer offset to a correct value.
+        * For asynchronous IOs, zonefs_file_write_dio_end_io() may already
+        * have executed error recovery if the IO already completed when we
+        * reach here. However, we cannot know that and execute error recovery
+        * again (that will not change anything).
+        */
+       if (zonefs_zone_is_seq(z)) {
+               if (ret > 0 && ret != count)
+                       ret = -EIO;
+               if (ret < 0 && ret != -EIOCBQUEUED)
+                       zonefs_io_error(inode, true);
        }
 
 inode_unlock:
index 93971742613a399d07fa2cf7e1f88cba61a91956..b6e8e7c96251d51f85c7183fa2e14352c5171ac2 100644 (file)
@@ -246,16 +246,18 @@ static void zonefs_inode_update_mode(struct inode *inode)
        z->z_mode = inode->i_mode;
 }
 
-struct zonefs_ioerr_data {
-       struct inode    *inode;
-       bool            write;
-};
-
 static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
                              void *data)
 {
-       struct zonefs_ioerr_data *err = data;
-       struct inode *inode = err->inode;
+       struct blk_zone *z = data;
+
+       *z = *zone;
+       return 0;
+}
+
+static void zonefs_handle_io_error(struct inode *inode, struct blk_zone *zone,
+                                  bool write)
+{
        struct zonefs_zone *z = zonefs_inode_zone(inode);
        struct super_block *sb = inode->i_sb;
        struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
@@ -270,8 +272,8 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
        data_size = zonefs_check_zone_condition(sb, z, zone);
        isize = i_size_read(inode);
        if (!(z->z_flags & (ZONEFS_ZONE_READONLY | ZONEFS_ZONE_OFFLINE)) &&
-           !err->write && isize == data_size)
-               return 0;
+           !write && isize == data_size)
+               return;
 
        /*
         * At this point, we detected either a bad zone or an inconsistency
@@ -292,7 +294,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
         * In all cases, warn about inode size inconsistency and handle the
         * IO error according to the zone condition and to the mount options.
         */
-       if (zonefs_zone_is_seq(z) && isize != data_size)
+       if (isize != data_size)
                zonefs_warn(sb,
                            "inode %lu: invalid size %lld (should be %lld)\n",
                            inode->i_ino, isize, data_size);
@@ -352,8 +354,6 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
        zonefs_i_size_write(inode, data_size);
        z->z_wpoffset = data_size;
        zonefs_inode_account_active(inode);
-
-       return 0;
 }
 
 /*
@@ -367,23 +367,25 @@ void __zonefs_io_error(struct inode *inode, bool write)
 {
        struct zonefs_zone *z = zonefs_inode_zone(inode);
        struct super_block *sb = inode->i_sb;
-       struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
        unsigned int noio_flag;
-       unsigned int nr_zones = 1;
-       struct zonefs_ioerr_data err = {
-               .inode = inode,
-               .write = write,
-       };
+       struct blk_zone zone;
        int ret;
 
        /*
-        * The only files that have more than one zone are conventional zone
-        * files with aggregated conventional zones, for which the inode zone
-        * size is always larger than the device zone size.
+        * Conventional zone have no write pointer and cannot become read-only
+        * or offline. So simply fake a report for a single or aggregated zone
+        * and let zonefs_handle_io_error() correct the zone inode information
+        * according to the mount options.
         */
-       if (z->z_size > bdev_zone_sectors(sb->s_bdev))
-               nr_zones = z->z_size >>
-                       (sbi->s_zone_sectors_shift + SECTOR_SHIFT);
+       if (!zonefs_zone_is_seq(z)) {
+               zone.start = z->z_sector;
+               zone.len = z->z_size >> SECTOR_SHIFT;
+               zone.wp = zone.start + zone.len;
+               zone.type = BLK_ZONE_TYPE_CONVENTIONAL;
+               zone.cond = BLK_ZONE_COND_NOT_WP;
+               zone.capacity = zone.len;
+               goto handle_io_error;
+       }
 
        /*
         * Memory allocations in blkdev_report_zones() can trigger a memory
@@ -394,12 +396,20 @@ void __zonefs_io_error(struct inode *inode, bool write)
         * the GFP_NOIO context avoids both problems.
         */
        noio_flag = memalloc_noio_save();
-       ret = blkdev_report_zones(sb->s_bdev, z->z_sector, nr_zones,
-                                 zonefs_io_error_cb, &err);
-       if (ret != nr_zones)
+       ret = blkdev_report_zones(sb->s_bdev, z->z_sector, 1,
+                                 zonefs_io_error_cb, &zone);
+       memalloc_noio_restore(noio_flag);
+
+       if (ret != 1) {
                zonefs_err(sb, "Get inode %lu zone information failed %d\n",
                           inode->i_ino, ret);
-       memalloc_noio_restore(noio_flag);
+               zonefs_warn(sb, "remounting filesystem read-only\n");
+               sb->s_flags |= SB_RDONLY;
+               return;
+       }
+
+handle_io_error:
+       zonefs_handle_io_error(inode, &zone, write);
 }
 
 static struct kmem_cache *zonefs_inode_cachep;
index ae12696ec492c67339409904bb612e9fdc372689..2ad261082bba5f6f0049fa1c642b6ff057f32b5a 100644 (file)
@@ -141,8 +141,6 @@ struct bdi_writeback {
        struct delayed_work dwork;      /* work item used for writeback */
        struct delayed_work bw_dwork;   /* work item used for bandwidth estimate */
 
-       unsigned long dirty_sleep;      /* last wait */
-
        struct list_head bdi_node;      /* anchored at bdi->wb_list */
 
 #ifdef CONFIG_CGROUP_WRITEBACK
@@ -179,6 +177,11 @@ struct backing_dev_info {
         * any dirty wbs, which is depended upon by bdi_has_dirty().
         */
        atomic_long_t tot_write_bandwidth;
+       /*
+        * Jiffies when last process was dirty throttled on this bdi. Used by
+        * blk-wbt.
+        */
+       unsigned long last_bdp_sleep;
 
        struct bdi_writeback wb;  /* the root writeback info for this bdi */
        struct list_head wb_list; /* list of all wbs */
index 2eaaabbe98cb64d3f64a698a6f527e244649ca4e..1717cc57cdacd3532e5de7d35f1c2d6eb4e1ef5b 100644 (file)
@@ -283,7 +283,7 @@ struct ceph_msg {
        struct kref kref;
        bool more_to_follow;
        bool needs_out_seq;
-       bool sparse_read;
+       u64 sparse_read_total;
        int front_alloc_len;
 
        struct ceph_msgpool *pool;
index fa018d5864e7422c522194c16ff45a8dd0db1376..f66f6aac74f6f108ffba40b62159e047a184b732 100644 (file)
@@ -45,6 +45,7 @@ enum ceph_sparse_read_state {
        CEPH_SPARSE_READ_HDR    = 0,
        CEPH_SPARSE_READ_EXTENTS,
        CEPH_SPARSE_READ_DATA_LEN,
+       CEPH_SPARSE_READ_DATA_PRE,
        CEPH_SPARSE_READ_DATA,
 };
 
@@ -64,7 +65,7 @@ struct ceph_sparse_read {
        u64                             sr_req_len;  /* orig request length */
        u64                             sr_pos;      /* current pos in buffer */
        int                             sr_index;    /* current extent index */
-       __le32                          sr_datalen;  /* length of actual data */
+       u32                             sr_datalen;  /* length of actual data */
        u32                             sr_count;    /* extent count in reply */
        int                             sr_ext_len;  /* length of extent array */
        struct ceph_sparse_extent       *sr_extent;  /* extent array */
index aebb65bf95a7988dfe8cf9cb1b5ec0945640ced3..75bd1692d2e3791c8122cdce74ebfd67032fee14 100644 (file)
                __builtin_unreachable();        \
        } while (0)
 
+/*
+ * GCC 'asm goto' with outputs miscompiles certain code sequences:
+ *
+ *   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921
+ *
+ * Work around it via the same compiler barrier quirk that we used
+ * to use for the old 'asm goto' workaround.
+ *
+ * Also, always mark such 'asm goto' statements as volatile: all
+ * asm goto statements are supposed to be volatile as per the
+ * documentation, but some versions of gcc didn't actually do
+ * that for asms with outputs:
+ *
+ *    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98619
+ */
+#ifdef CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND
+#define asm_goto_output(x...) \
+       do { asm volatile goto(x); asm (""); } while (0)
+#endif
+
 #if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP)
 #define __HAVE_BUILTIN_BSWAP32__
 #define __HAVE_BUILTIN_BSWAP64__
index 6f1ca49306d2f7e7b51817fc579b82a85246736d..0caf354cb94b5ad9d802addff81a1bd1c3250139 100644 (file)
@@ -362,8 +362,15 @@ struct ftrace_likely_data {
 #define __member_size(p)       __builtin_object_size(p, 1)
 #endif
 
-#ifndef asm_volatile_goto
-#define asm_volatile_goto(x...) asm goto(x)
+/*
+ * Some versions of gcc do not mark 'asm goto' volatile:
+ *
+ *  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103979
+ *
+ * We do it here by hand, because it doesn't hurt.
+ */
+#ifndef asm_goto_output
+#define asm_goto_output(x...) asm volatile goto(x)
 #endif
 
 #ifdef CONFIG_CC_HAS_ASM_INLINE
index c1a7dc3251215a5ba0e982568a746ff5b04602d1..265b0f8fc0b3c876191ba94bbc2d1d9dd66dd848 100644 (file)
@@ -90,6 +90,29 @@ enum {
        GUID_INIT(0x667DD791, 0xC6B3, 0x4c27, 0x8A, 0x6B, 0x0F, 0x8E,   \
                  0x72, 0x2D, 0xEB, 0x41)
 
+/* CXL Event record UUIDs are formatted as GUIDs and reported in section type */
+/*
+ * General Media Event Record
+ * CXL rev 3.0 Section 8.2.9.2.1.1; Table 8-43
+ */
+#define CPER_SEC_CXL_GEN_MEDIA_GUID                                    \
+       GUID_INIT(0xfbcd0a77, 0xc260, 0x417f,                           \
+                 0x85, 0xa9, 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6)
+/*
+ * DRAM Event Record
+ * CXL rev 3.0 section 8.2.9.2.1.2; Table 8-44
+ */
+#define CPER_SEC_CXL_DRAM_GUID                                         \
+       GUID_INIT(0x601dcbb3, 0x9c06, 0x4eab,                           \
+                 0xb8, 0xaf, 0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24)
+/*
+ * Memory Module Event Record
+ * CXL rev 3.0 section 8.2.9.2.1.3; Table 8-45
+ */
+#define CPER_SEC_CXL_MEM_MODULE_GUID                                   \
+       GUID_INIT(0xfe927475, 0xdd59, 0x4339,                           \
+                 0xa5, 0x86, 0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74)
+
 /*
  * Flags bits definitions for flags in struct cper_record_header
  * If set, the error has been recovered
index ed5966a70495129be1d6729eed2918240db62df1..023f37c607094a5339598ac2c7dddd09745c907e 100644 (file)
@@ -2101,9 +2101,6 @@ int __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
 int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
                                  struct file *file_out, loff_t pos_out,
                                  loff_t *count, unsigned int remap_flags);
-extern loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
-                                 struct file *file_out, loff_t pos_out,
-                                 loff_t len, unsigned int remap_flags);
 extern loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
                                   struct file *file_out, loff_t pos_out,
                                   loff_t len, unsigned int remap_flags);
index 9a5c6c76e6533385dbb32de98abfd330c8736585..7f75c9a5187417b3b52386573a47f7c1e95e9126 100644 (file)
@@ -819,6 +819,24 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
        return ERR_PTR(-ENODEV);
 }
 
+static inline struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc)
+{
+       WARN_ON(1);
+       return ERR_PTR(-ENODEV);
+}
+
+static inline int gpio_device_get_base(struct gpio_device *gdev)
+{
+       WARN_ON(1);
+       return -ENODEV;
+}
+
+static inline const char *gpio_device_get_label(struct gpio_device *gdev)
+{
+       WARN_ON(1);
+       return NULL;
+}
+
 static inline int gpiochip_lock_as_irq(struct gpio_chip *gc,
                                       unsigned int offset)
 {
index 87e3bedf8eb00323c102787243e7dbfd045ba4e9..641c4567cfa7aee830f8ad0b52abb24bcbe353a8 100644 (file)
@@ -157,6 +157,7 @@ enum  hrtimer_base_type {
  * @max_hang_time:     Maximum time spent in hrtimer_interrupt
  * @softirq_expiry_lock: Lock which is taken while softirq based hrtimer are
  *                      expired
+ * @online:            CPU is online from an hrtimers point of view
  * @timer_waiters:     A hrtimer_cancel() invocation waits for the timer
  *                     callback to finish.
  * @expires_next:      absolute time of the next event, is required for remote
@@ -179,7 +180,8 @@ struct hrtimer_cpu_base {
        unsigned int                    hres_active             : 1,
                                        in_hrtirq               : 1,
                                        hang_detected           : 1,
-                                       softirq_activated       : 1;
+                                       softirq_activated       : 1,
+                                       online                  : 1;
 #ifdef CONFIG_HIGH_RES_TIMERS
        unsigned int                    nr_events;
        unsigned short                  nr_retries;
index 118c40258d07b787adf518e576e75545e4bae846..ef7bfbb9849733fa7f1f097ba53a36a68cc3384b 100644 (file)
@@ -2141,6 +2141,11 @@ struct net_device {
 
        /* TXRX read-mostly hotpath */
        __cacheline_group_begin(net_device_read_txrx);
+       union {
+               struct pcpu_lstats __percpu             *lstats;
+               struct pcpu_sw_netstats __percpu        *tstats;
+               struct pcpu_dstats __percpu             *dstats;
+       };
        unsigned int            flags;
        unsigned short          hard_header_len;
        netdev_features_t       features;
@@ -2395,11 +2400,6 @@ struct net_device {
        enum netdev_ml_priv_type        ml_priv_type;
 
        enum netdev_stat_type           pcpu_stat_type:8;
-       union {
-               struct pcpu_lstats __percpu             *lstats;
-               struct pcpu_sw_netstats __percpu        *tstats;
-               struct pcpu_dstats __percpu             *dstats;
-       };
 
 #if IS_ENABLED(CONFIG_GARP)
        struct garp_port __rcu  *garp_port;
index bc605ec4a3fd06f9145242827fe310a760f00122..3ef4053ea9500bc975acd5433ff387633c92eb62 100644 (file)
@@ -646,6 +646,7 @@ enum {
        NVME_CMD_EFFECTS_NCC            = 1 << 2,
        NVME_CMD_EFFECTS_NIC            = 1 << 3,
        NVME_CMD_EFFECTS_CCC            = 1 << 4,
+       NVME_CMD_EFFECTS_CSER_MASK      = GENMASK(15, 14),
        NVME_CMD_EFFECTS_CSE_MASK       = GENMASK(18, 16),
        NVME_CMD_EFFECTS_UUID_SEL       = 1 << 19,
        NVME_CMD_EFFECTS_SCOPE_MASK     = GENMASK(31, 20),
index eaaef3ffec221b93cfbb9a2f4c20646b473754fa..90507d4afcd6debb80eef494c4c874c8a1732e49 100644 (file)
@@ -393,6 +393,10 @@ static inline void user_single_step_report(struct pt_regs *regs)
 #define current_user_stack_pointer() user_stack_pointer(current_pt_regs())
 #endif
 
+#ifndef exception_ip
+#define exception_ip(x) instruction_pointer(x)
+#endif
+
 extern int task_current_syscall(struct task_struct *target, struct syscall_info *info);
 
 extern void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact);
index c44f4b47b945306318d8ed164c498abfe2512a10..fe41da0059700432044c1260952073914f7a26fc 100644 (file)
@@ -2,7 +2,10 @@
 #ifndef _LINUX_SEQ_BUF_H
 #define _LINUX_SEQ_BUF_H
 
-#include <linux/fs.h>
+#include <linux/bug.h>
+#include <linux/minmax.h>
+#include <linux/seq_file.h>
+#include <linux/types.h>
 
 /*
  * Trace sequences are used to allow a function to call several other functions
@@ -10,7 +13,7 @@
  */
 
 /**
- * seq_buf - seq buffer structure
+ * struct seq_buf - seq buffer structure
  * @buffer:    pointer to the buffer
  * @size:      size of the buffer
  * @len:       the amount of data inside the buffer
@@ -77,10 +80,10 @@ static inline unsigned int seq_buf_used(struct seq_buf *s)
 }
 
 /**
- * seq_buf_str - get %NUL-terminated C string from seq_buf
+ * seq_buf_str - get NUL-terminated C string from seq_buf
  * @s: the seq_buf handle
  *
- * This makes sure that the buffer in @s is nul terminated and
+ * This makes sure that the buffer in @s is NUL-terminated and
  * safe to read as a string.
  *
  * Note, if this is called when the buffer has overflowed, then
@@ -90,7 +93,7 @@ static inline unsigned int seq_buf_used(struct seq_buf *s)
  * After this function is called, s->buffer is safe to use
  * in string operations.
  *
- * Returns @s->buf after making sure it is terminated.
+ * Returns: @s->buf after making sure it is terminated.
  */
 static inline const char *seq_buf_str(struct seq_buf *s)
 {
@@ -110,7 +113,7 @@ static inline const char *seq_buf_str(struct seq_buf *s)
  * @s: the seq_buf handle
  * @bufp: the beginning of the buffer is stored here
  *
- * Return the number of bytes available in the buffer, or zero if
+ * Returns: the number of bytes available in the buffer, or zero if
  * there's no space.
  */
 static inline size_t seq_buf_get_buf(struct seq_buf *s, char **bufp)
@@ -132,7 +135,7 @@ static inline size_t seq_buf_get_buf(struct seq_buf *s, char **bufp)
  * @num: the number of bytes to commit
  *
  * Commit @num bytes of data written to a buffer previously acquired
- * by seq_buf_get To signal an error condition, or that the data
+ * by seq_buf_get_buf(). To signal an error condition, or that the data
  * didn't fit in the available space, pass a negative @num value.
  */
 static inline void seq_buf_commit(struct seq_buf *s, int num)
index 536b2581d3e2007593323a53c050d037d6ac5dd1..55b1f3ba48ac1725f110747b8d05ce6bbfc1de0b 100644 (file)
@@ -748,8 +748,17 @@ struct uart_driver {
 
 void uart_write_wakeup(struct uart_port *port);
 
-#define __uart_port_tx(uport, ch, tx_ready, put_char, tx_done, for_test,      \
-               for_post)                                                     \
+/**
+ * enum UART_TX_FLAGS -- flags for uart_port_tx_flags()
+ *
+ * @UART_TX_NOSTOP: don't call port->ops->stop_tx() on empty buffer
+ */
+enum UART_TX_FLAGS {
+       UART_TX_NOSTOP = BIT(0),
+};
+
+#define __uart_port_tx(uport, ch, flags, tx_ready, put_char, tx_done,        \
+                      for_test, for_post)                                    \
 ({                                                                           \
        struct uart_port *__port = (uport);                                   \
        struct circ_buf *xmit = &__port->state->xmit;                         \
@@ -777,7 +786,7 @@ void uart_write_wakeup(struct uart_port *port);
        if (pending < WAKEUP_CHARS) {                                         \
                uart_write_wakeup(__port);                                    \
                                                                              \
-               if (pending == 0)                                             \
+               if (!((flags) & UART_TX_NOSTOP) && pending == 0)              \
                        __port->ops->stop_tx(__port);                         \
        }                                                                     \
                                                                              \
@@ -812,7 +821,7 @@ void uart_write_wakeup(struct uart_port *port);
  */
 #define uart_port_tx_limited(port, ch, count, tx_ready, put_char, tx_done) ({ \
        unsigned int __count = (count);                                       \
-       __uart_port_tx(port, ch, tx_ready, put_char, tx_done, __count,        \
+       __uart_port_tx(port, ch, 0, tx_ready, put_char, tx_done, __count,     \
                        __count--);                                           \
 })
 
@@ -826,8 +835,21 @@ void uart_write_wakeup(struct uart_port *port);
  * See uart_port_tx_limited() for more details.
  */
 #define uart_port_tx(port, ch, tx_ready, put_char)                     \
-       __uart_port_tx(port, ch, tx_ready, put_char, ({}), true, ({}))
+       __uart_port_tx(port, ch, 0, tx_ready, put_char, ({}), true, ({}))
+
 
+/**
+ * uart_port_tx_flags -- transmit helper for uart_port with flags
+ * @port: uart port
+ * @ch: variable to store a character to be written to the HW
+ * @flags: %UART_TX_NOSTOP or similar
+ * @tx_ready: can HW accept more data function
+ * @put_char: function to write a character
+ *
+ * See uart_port_tx_limited() for more details.
+ */
+#define uart_port_tx_flags(port, ch, flags, tx_ready, put_char)                \
+       __uart_port_tx(port, ch, flags, tx_ready, put_char, ({}), true, ({}))
 /*
  * Baud rate helpers.
  */
index 89b290d8c8dc9f115df7a295bc8d2512698db169..a1c47a6d69b0efd7e62765fbd873c848da22aaec 100644 (file)
@@ -221,8 +221,10 @@ struct tcp_sock {
        u32     lost_out;       /* Lost packets                 */
        u32     sacked_out;     /* SACK'd packets                       */
        u16     tcp_header_len; /* Bytes of tcp header to send          */
+       u8      scaling_ratio;  /* see tcp_win_from_space() */
        u8      chrono_type : 2,        /* current chronograph type */
                repair      : 1,
+               tcp_usec_ts : 1, /* TSval values in usec */
                is_sack_reneg:1,    /* in recovery from loss with SACK reneg? */
                is_cwnd_limited:1;/* forward progress limited by snd_cwnd? */
        __cacheline_group_end(tcp_sock_read_txrx);
@@ -352,7 +354,6 @@ struct tcp_sock {
        u32     compressed_ack_rcv_nxt;
        struct list_head tsq_node; /* anchor in tsq_tasklet.head list */
 
-       u8      scaling_ratio;  /* see tcp_win_from_space() */
        /* Information of the most recently (s)acked skb */
        struct tcp_rack {
                u64 mstamp; /* (Re)sent time of the skb */
@@ -368,8 +369,7 @@ struct tcp_sock {
        u8      compressed_ack;
        u8      dup_ack_counter:2,
                tlp_retrans:1,  /* TLP is a retransmission */
-               tcp_usec_ts:1, /* TSval values in usec */
-               unused:4;
+               unused:5;
        u8      thin_lto    : 1,/* Use linear timeouts for thin streams */
                recvmsg_inq : 1,/* Indicate # of bytes in queue upon recvmsg */
                fastopen_connect:1, /* FASTOPEN_CONNECT sockopt */
index a771ccc038ac949f2b4a835e28d720735e17ee22..6532beb587b1978e09bc5b17dc088daf91f9f88c 100644 (file)
@@ -236,7 +236,6 @@ struct usb_ep {
        unsigned                max_streams:16;
        unsigned                mult:2;
        unsigned                maxburst:5;
-       unsigned                fifo_mode:1;
        u8                      address;
        const struct usb_endpoint_descriptor    *desc;
        const struct usb_ss_ep_comp_descriptor  *comp_desc;
index cf79656ce09ca1f05b733bfce2393f4a044d9454..2b54fdd8ca15a8fae0f810fc5ba550a1b1a44676 100644 (file)
@@ -2910,6 +2910,8 @@ struct cfg80211_bss_ies {
  *     own the beacon_ies, but they're just pointers to the ones from the
  *     @hidden_beacon_bss struct)
  * @proberesp_ies: the information elements from the last Probe Response frame
+ * @proberesp_ecsa_stuck: ECSA element is stuck in the Probe Response frame,
+ *     cannot rely on it having valid data
  * @hidden_beacon_bss: in case this BSS struct represents a probe response from
  *     a BSS that hides the SSID in its beacon, this points to the BSS struct
  *     that holds the beacon data. @beacon_ies is still valid, of course, and
@@ -2950,6 +2952,8 @@ struct cfg80211_bss {
        u8 chains;
        s8 chain_signal[IEEE80211_MAX_CHAINS];
 
+       u8 proberesp_ecsa_stuck:1;
+
        u8 bssid_index;
        u8 max_bssid_indicator;
 
index 001226c34621560a49cffc85046df85f1c1fa4fe..510244cc0f8f0e479f252598ba2aaf43b8918978 100644 (file)
@@ -808,10 +808,16 @@ static inline struct nft_set_elem_expr *nft_set_ext_expr(const struct nft_set_ex
        return nft_set_ext(ext, NFT_SET_EXT_EXPRESSIONS);
 }
 
-static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
+static inline bool __nft_set_elem_expired(const struct nft_set_ext *ext,
+                                         u64 tstamp)
 {
        return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
-              time_is_before_eq_jiffies64(*nft_set_ext_expiration(ext));
+              time_after_eq64(tstamp, *nft_set_ext_expiration(ext));
+}
+
+static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
+{
+       return __nft_set_elem_expired(ext, get_jiffies_64());
 }
 
 static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
@@ -1779,6 +1785,7 @@ struct nftables_pernet {
        struct list_head        notify_list;
        struct mutex            commit_mutex;
        u64                     table_handle;
+       u64                     tstamp;
        unsigned int            base_seq;
        unsigned int            gc_seq;
        u8                      validate_state;
@@ -1791,6 +1798,11 @@ static inline struct nftables_pernet *nft_pernet(const struct net *net)
        return net_generic(net, nf_tables_net_id);
 }
 
+static inline u64 nft_net_tstamp(const struct net *net)
+{
+       return nft_pernet(net)->tstamp;
+}
+
 #define __NFT_REDUCE_READONLY  1UL
 #define NFT_REDUCE_READONLY    (void *)__NFT_REDUCE_READONLY
 
index 962f0c501111bac34781c4419913540c162ea058..340ad43971e4711d8091a6397bb5cf3c3c4ef0fd 100644 (file)
@@ -97,9 +97,6 @@ struct tls_sw_context_tx {
        struct tls_rec *open_rec;
        struct list_head tx_list;
        atomic_t encrypt_pending;
-       /* protect crypto_wait with encrypt_pending */
-       spinlock_t encrypt_compl_lock;
-       int async_notify;
        u8 async_capable:1;
 
 #define BIT_TX_SCHEDULED       0
@@ -136,8 +133,6 @@ struct tls_sw_context_rx {
        struct tls_strparser strp;
 
        atomic_t decrypt_pending;
-       /* protect crypto_wait with decrypt_pending*/
-       spinlock_t decrypt_compl_lock;
        struct sk_buff_head async_hold;
        struct wait_queue_head wq;
 };
index b00d65417c310a42a39aec6ce927b85083ace264..9aff384941de27f925d0491312a7088ebeb6a297 100644 (file)
@@ -142,6 +142,7 @@ struct tasdevice_priv {
 
 void tas2781_reset(struct tasdevice_priv *tas_dev);
 int tascodec_init(struct tasdevice_priv *tas_priv, void *codec,
+       struct module *module,
        void (*cont)(const struct firmware *fw, void *context));
 struct tasdevice_priv *tasdevice_kzalloc(struct i2c_client *i2c);
 int tasdevice_init(struct tasdevice_priv *tas_priv);
index 4c1ef7b3705c26baf79c135f235c94195635bf4b..87b8de9b6c1c440ce4a8b2fe6072b4d81cbc1cf4 100644 (file)
        EM(rxrpc_skb_eaten_by_unshare_nomem,    "ETN unshar-nm") \
        EM(rxrpc_skb_get_conn_secured,          "GET conn-secd") \
        EM(rxrpc_skb_get_conn_work,             "GET conn-work") \
+       EM(rxrpc_skb_get_last_nack,             "GET last-nack") \
        EM(rxrpc_skb_get_local_work,            "GET locl-work") \
        EM(rxrpc_skb_get_reject_work,           "GET rej-work ") \
        EM(rxrpc_skb_get_to_recvmsg,            "GET to-recv  ") \
        EM(rxrpc_skb_put_error_report,          "PUT error-rep") \
        EM(rxrpc_skb_put_input,                 "PUT input    ") \
        EM(rxrpc_skb_put_jumbo_subpacket,       "PUT jumbo-sub") \
+       EM(rxrpc_skb_put_last_nack,             "PUT last-nack") \
        EM(rxrpc_skb_put_purge,                 "PUT purge    ") \
        EM(rxrpc_skb_put_rotate,                "PUT rotate   ") \
        EM(rxrpc_skb_put_unknown,               "PUT unknown  ") \
@@ -1552,7 +1554,7 @@ TRACE_EVENT(rxrpc_congest,
                    memcpy(&__entry->sum, summary, sizeof(__entry->sum));
                           ),
 
-           TP_printk("c=%08x r=%08x %s q=%08x %s cw=%u ss=%u nA=%u,%u+%u r=%u b=%u u=%u d=%u l=%x%s%s%s",
+           TP_printk("c=%08x r=%08x %s q=%08x %s cw=%u ss=%u nA=%u,%u+%u,%u b=%u u=%u d=%u l=%x%s%s%s",
                      __entry->call,
                      __entry->ack_serial,
                      __print_symbolic(__entry->sum.ack_reason, rxrpc_ack_names),
@@ -1560,9 +1562,9 @@ TRACE_EVENT(rxrpc_congest,
                      __print_symbolic(__entry->sum.mode, rxrpc_congest_modes),
                      __entry->sum.cwnd,
                      __entry->sum.ssthresh,
-                     __entry->sum.nr_acks, __entry->sum.saw_nacks,
+                     __entry->sum.nr_acks, __entry->sum.nr_retained_nacks,
                      __entry->sum.nr_new_acks,
-                     __entry->sum.nr_rot_new_acks,
+                     __entry->sum.nr_new_nacks,
                      __entry->top - __entry->hard_ack,
                      __entry->sum.cumulative_acks,
                      __entry->sum.dup_acks,
index 63c49318a863076b0861b945c1511d98f9ffffe3..19a13468eca5e4c13cbdf05444604a54567a67ae 100644 (file)
@@ -305,6 +305,7 @@ struct drm_ivpu_submit {
 
 /* drm_ivpu_bo_wait job status codes */
 #define DRM_IVPU_JOB_STATUS_SUCCESS 0
+#define DRM_IVPU_JOB_STATUS_ABORTED 256
 
 /**
  * struct drm_ivpu_bo_wait - Wait for BO to become inactive
index ca30232b7bc8af49a6c3dd1c03e105628aafabf9..117c6a9b845b1a6fde23a952560c0e807a5a3d90 100644 (file)
@@ -285,9 +285,11 @@ enum nft_rule_attributes {
 /**
  * enum nft_rule_compat_flags - nf_tables rule compat flags
  *
+ * @NFT_RULE_COMPAT_F_UNUSED: unused
  * @NFT_RULE_COMPAT_F_INV: invert the check result
  */
 enum nft_rule_compat_flags {
+       NFT_RULE_COMPAT_F_UNUSED = (1 << 0),
        NFT_RULE_COMPAT_F_INV   = (1 << 1),
        NFT_RULE_COMPAT_F_MASK  = NFT_RULE_COMPAT_F_INV,
 };
index 48d2790ef928c798279babb69fbd07f7d6dcc20d..3109282672f33cecc00cd3f08e9dfd22e7991637 100644 (file)
@@ -31,7 +31,10 @@ struct ioctl_gntalloc_alloc_gref {
        __u64 index;
        /* The grant references of the newly created grant, one per page */
        /* Variable size, depending on count */
-       __u32 gref_ids[1];
+       union {
+               __u32 gref_ids[1];
+               __DECLARE_FLEX_ARRAY(__u32, gref_ids_flex);
+       };
 };
 
 #define GNTALLOC_FLAG_WRITABLE 1
index deda3d14135bb9ed54469353e44f1c1e86e8a0f2..8426d59cc634d6dc86cc9954072a425b277c24ea 100644 (file)
@@ -89,6 +89,15 @@ config CC_HAS_ASM_GOTO_TIED_OUTPUT
        # Detect buggy gcc and clang, fixed in gcc-11 clang-14.
        def_bool $(success,echo 'int foo(int *x) { asm goto (".long (%l[bar]) - .": "+m"(*x) ::: bar); return *x; bar: return 0; }' | $CC -x c - -c -o /dev/null)
 
+config GCC_ASM_GOTO_OUTPUT_WORKAROUND
+       bool
+       depends on CC_IS_GCC && CC_HAS_ASM_GOTO_OUTPUT
+       # Fixed in GCC 14, 13.3, 12.4 and 11.5
+       # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921
+       default y if GCC_VERSION < 110500
+       default y if GCC_VERSION >= 120000 && GCC_VERSION < 120400
+       default y if GCC_VERSION >= 130000 && GCC_VERSION < 130300
+
 config TOOLS_SUPPORT_RELR
        def_bool $(success,env "CC=$(CC)" "LD=$(LD)" "NM=$(NM)" "OBJCOPY=$(OBJCOPY)" $(srctree)/scripts/tools-support-relr.sh)
 
index 43bc9a5f96f9d1ce48f2d6e2a5cf850c675aee0d..161622029147ca3e6c13784274ea084d05695ccc 100644 (file)
@@ -1372,7 +1372,7 @@ retry:
                         * has already been done
                         */
                        if (issue_flags & IO_URING_F_MULTISHOT)
-                               ret = IOU_ISSUE_SKIP_COMPLETE;
+                               return IOU_ISSUE_SKIP_COMPLETE;
                        return ret;
                }
                if (ret == -ERESTARTSYS)
@@ -1397,7 +1397,8 @@ retry:
                                ret, IORING_CQE_F_MORE))
                goto retry;
 
-       return -ECANCELED;
+       io_req_set_res(req, ret, 0);
+       return IOU_STOP_MULTISHOT;
 }
 
 int io_socket_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
index 3988a02efaef06444654a415ce298d378ab925ec..dfb963d2f862ada6a2f06259c6df4923272cb218 100644 (file)
@@ -1127,17 +1127,14 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
                 * and nobody can change them.
                 *
                 * psig->stats_lock also protects us from our sub-threads
-                * which can reap other children at the same time. Until
-                * we change k_getrusage()-like users to rely on this lock
-                * we have to take ->siglock as well.
+                * which can reap other children at the same time.
                 *
                 * We use thread_group_cputime_adjusted() to get times for
                 * the thread group, which consolidates times for all threads
                 * in the group including the group leader.
                 */
                thread_group_cputime_adjusted(p, &tgutime, &tgstime);
-               spin_lock_irq(&current->sighand->siglock);
-               write_seqlock(&psig->stats_lock);
+               write_seqlock_irq(&psig->stats_lock);
                psig->cutime += tgutime + sig->cutime;
                psig->cstime += tgstime + sig->cstime;
                psig->cgtime += task_gtime(p) + sig->gtime + sig->cgtime;
@@ -1160,8 +1157,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
                        psig->cmaxrss = maxrss;
                task_io_accounting_add(&psig->ioac, &p->ioac);
                task_io_accounting_add(&psig->ioac, &sig->ioac);
-               write_sequnlock(&psig->stats_lock);
-               spin_unlock_irq(&current->sighand->siglock);
+               write_sequnlock_irq(&psig->stats_lock);
        }
 
        if (wo->wo_rusage)
index d5a0ee40bf66c5318df14c5a49294850434e13d3..9d9095e817928658d2c6d54d5da6f4826ff7c6be 100644 (file)
@@ -1993,7 +1993,7 @@ NOKPROBE_SYMBOL(__kretprobe_find_ret_addr);
 unsigned long kretprobe_find_ret_addr(struct task_struct *tsk, void *fp,
                                      struct llist_node **cur)
 {
-       struct kretprobe_instance *ri = NULL;
+       struct kretprobe_instance *ri;
        kprobe_opcode_t *ret;
 
        if (WARN_ON_ONCE(!cur))
@@ -2802,7 +2802,7 @@ static int show_kprobe_addr(struct seq_file *pi, void *v)
 {
        struct hlist_head *head;
        struct kprobe *p, *kp;
-       const char *sym = NULL;
+       const char *sym;
        unsigned int i = *(loff_t *) v;
        unsigned long offset = 0;
        char *modname, namebuf[KSYM_NAME_LEN];
index e219fcfa112d863eeef58381d04fd4bab16a1e32..f8e543f1e38a06dc3a4aa2f777c7e88d444e5565 100644 (file)
@@ -1785,21 +1785,24 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
        struct task_struct *t;
        unsigned long flags;
        u64 tgutime, tgstime, utime, stime;
-       unsigned long maxrss = 0;
+       unsigned long maxrss;
+       struct mm_struct *mm;
        struct signal_struct *sig = p->signal;
+       unsigned int seq = 0;
 
-       memset((char *)r, 0, sizeof (*r));
+retry:
+       memset(r, 0, sizeof(*r));
        utime = stime = 0;
+       maxrss = 0;
 
        if (who == RUSAGE_THREAD) {
                task_cputime_adjusted(current, &utime, &stime);
                accumulate_thread_rusage(p, r);
                maxrss = sig->maxrss;
-               goto out;
+               goto out_thread;
        }
 
-       if (!lock_task_sighand(p, &flags))
-               return;
+       flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
 
        switch (who) {
        case RUSAGE_BOTH:
@@ -1819,9 +1822,6 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
                fallthrough;
 
        case RUSAGE_SELF:
-               thread_group_cputime_adjusted(p, &tgutime, &tgstime);
-               utime += tgutime;
-               stime += tgstime;
                r->ru_nvcsw += sig->nvcsw;
                r->ru_nivcsw += sig->nivcsw;
                r->ru_minflt += sig->min_flt;
@@ -1830,28 +1830,42 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
                r->ru_oublock += sig->oublock;
                if (maxrss < sig->maxrss)
                        maxrss = sig->maxrss;
+
+               rcu_read_lock();
                __for_each_thread(sig, t)
                        accumulate_thread_rusage(t, r);
+               rcu_read_unlock();
+
                break;
 
        default:
                BUG();
        }
-       unlock_task_sighand(p, &flags);
 
-out:
-       r->ru_utime = ns_to_kernel_old_timeval(utime);
-       r->ru_stime = ns_to_kernel_old_timeval(stime);
+       if (need_seqretry(&sig->stats_lock, seq)) {
+               seq = 1;
+               goto retry;
+       }
+       done_seqretry_irqrestore(&sig->stats_lock, seq, flags);
 
-       if (who != RUSAGE_CHILDREN) {
-               struct mm_struct *mm = get_task_mm(p);
+       if (who == RUSAGE_CHILDREN)
+               goto out_children;
 
-               if (mm) {
-                       setmax_mm_hiwater_rss(&maxrss, mm);
-                       mmput(mm);
-               }
+       thread_group_cputime_adjusted(p, &tgutime, &tgstime);
+       utime += tgutime;
+       stime += tgstime;
+
+out_thread:
+       mm = get_task_mm(p);
+       if (mm) {
+               setmax_mm_hiwater_rss(&maxrss, mm);
+               mmput(mm);
        }
+
+out_children:
        r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
+       r->ru_utime = ns_to_kernel_old_timeval(utime);
+       r->ru_stime = ns_to_kernel_old_timeval(stime);
 }
 
 SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
index 760793998cdd703a387c64a792a7b7f7dab552d5..edb0f821dceaa1720ac94fc53f4002a1e5f7bdd3 100644 (file)
@@ -1085,6 +1085,7 @@ static int enqueue_hrtimer(struct hrtimer *timer,
                           enum hrtimer_mode mode)
 {
        debug_activate(timer, mode);
+       WARN_ON_ONCE(!base->cpu_base->online);
 
        base->cpu_base->active_bases |= 1 << base->index;
 
@@ -2183,6 +2184,7 @@ int hrtimers_prepare_cpu(unsigned int cpu)
        cpu_base->softirq_next_timer = NULL;
        cpu_base->expires_next = KTIME_MAX;
        cpu_base->softirq_expires_next = KTIME_MAX;
+       cpu_base->online = 1;
        hrtimer_cpu_base_init_expiry_lock(cpu_base);
        return 0;
 }
@@ -2250,6 +2252,7 @@ int hrtimers_cpu_dying(unsigned int dying_cpu)
        smp_call_function_single(ncpu, retrigger_next_event, NULL, 0);
 
        raw_spin_unlock(&new_base->lock);
+       old_base->online = 0;
        raw_spin_unlock(&old_base->lock);
 
        return 0;
index b01ae7d36021819e6d929ce2ab1e0a5a61464309..83ba342aef31f7d919f4c24a73d2c4cea76be137 100644 (file)
@@ -5325,7 +5325,17 @@ static LIST_HEAD(ftrace_direct_funcs);
 
 static int register_ftrace_function_nolock(struct ftrace_ops *ops);
 
+/*
+ * If there are multiple ftrace_ops, use SAVE_REGS by default, so that direct
+ * call will be jumped from ftrace_regs_caller. Only if the architecture does
+ * not support ftrace_regs_caller but direct_call, use SAVE_ARGS so that it
+ * jumps from ftrace_caller for multiple ftrace_ops.
+ */
+#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS
 #define MULTI_FLAGS (FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_ARGS)
+#else
+#define MULTI_FLAGS (FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_REGS)
+#endif
 
 static int check_direct_multi(struct ftrace_ops *ops)
 {
index 2a7c6fd934e9cb391b5ddf589748c572810ad6d1..8198bfc54b58d9729ab6f6318eb9720a32d40375 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/ctype.h>
 #include <linux/init.h>
 #include <linux/panic_notifier.h>
+#include <linux/kmemleak.h>
 #include <linux/poll.h>
 #include <linux/nmi.h>
 #include <linux/fs.h>
@@ -1532,7 +1533,7 @@ void disable_trace_on_warning(void)
 bool tracer_tracing_is_on(struct trace_array *tr)
 {
        if (tr->array_buffer.buffer)
-               return ring_buffer_record_is_on(tr->array_buffer.buffer);
+               return ring_buffer_record_is_set_on(tr->array_buffer.buffer);
        return !tr->buffer_disabled;
 }
 
@@ -2320,7 +2321,7 @@ struct saved_cmdlines_buffer {
        unsigned *map_cmdline_to_pid;
        unsigned cmdline_num;
        int cmdline_idx;
-       char *saved_cmdlines;
+       char saved_cmdlines[];
 };
 static struct saved_cmdlines_buffer *savedcmd;
 
@@ -2334,47 +2335,60 @@ static inline void set_cmdline(int idx, const char *cmdline)
        strncpy(get_saved_cmdlines(idx), cmdline, TASK_COMM_LEN);
 }
 
-static int allocate_cmdlines_buffer(unsigned int val,
-                                   struct saved_cmdlines_buffer *s)
+static void free_saved_cmdlines_buffer(struct saved_cmdlines_buffer *s)
+{
+       int order = get_order(sizeof(*s) + s->cmdline_num * TASK_COMM_LEN);
+
+       kfree(s->map_cmdline_to_pid);
+       kmemleak_free(s);
+       free_pages((unsigned long)s, order);
+}
+
+static struct saved_cmdlines_buffer *allocate_cmdlines_buffer(unsigned int val)
 {
+       struct saved_cmdlines_buffer *s;
+       struct page *page;
+       int orig_size, size;
+       int order;
+
+       /* Figure out how much is needed to hold the given number of cmdlines */
+       orig_size = sizeof(*s) + val * TASK_COMM_LEN;
+       order = get_order(orig_size);
+       size = 1 << (order + PAGE_SHIFT);
+       page = alloc_pages(GFP_KERNEL, order);
+       if (!page)
+               return NULL;
+
+       s = page_address(page);
+       kmemleak_alloc(s, size, 1, GFP_KERNEL);
+       memset(s, 0, sizeof(*s));
+
+       /* Round up to actual allocation */
+       val = (size - sizeof(*s)) / TASK_COMM_LEN;
+       s->cmdline_num = val;
+
        s->map_cmdline_to_pid = kmalloc_array(val,
                                              sizeof(*s->map_cmdline_to_pid),
                                              GFP_KERNEL);
-       if (!s->map_cmdline_to_pid)
-               return -ENOMEM;
-
-       s->saved_cmdlines = kmalloc_array(TASK_COMM_LEN, val, GFP_KERNEL);
-       if (!s->saved_cmdlines) {
-               kfree(s->map_cmdline_to_pid);
-               return -ENOMEM;
+       if (!s->map_cmdline_to_pid) {
+               free_saved_cmdlines_buffer(s);
+               return NULL;
        }
 
        s->cmdline_idx = 0;
-       s->cmdline_num = val;
        memset(&s->map_pid_to_cmdline, NO_CMDLINE_MAP,
               sizeof(s->map_pid_to_cmdline));
        memset(s->map_cmdline_to_pid, NO_CMDLINE_MAP,
               val * sizeof(*s->map_cmdline_to_pid));
 
-       return 0;
+       return s;
 }
 
 static int trace_create_savedcmd(void)
 {
-       int ret;
-
-       savedcmd = kmalloc(sizeof(*savedcmd), GFP_KERNEL);
-       if (!savedcmd)
-               return -ENOMEM;
-
-       ret = allocate_cmdlines_buffer(SAVED_CMDLINES_DEFAULT, savedcmd);
-       if (ret < 0) {
-               kfree(savedcmd);
-               savedcmd = NULL;
-               return -ENOMEM;
-       }
+       savedcmd = allocate_cmdlines_buffer(SAVED_CMDLINES_DEFAULT);
 
-       return 0;
+       return savedcmd ? 0 : -ENOMEM;
 }
 
 int is_tracing_stopped(void)
@@ -6056,26 +6070,14 @@ tracing_saved_cmdlines_size_read(struct file *filp, char __user *ubuf,
        return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
 }
 
-static void free_saved_cmdlines_buffer(struct saved_cmdlines_buffer *s)
-{
-       kfree(s->saved_cmdlines);
-       kfree(s->map_cmdline_to_pid);
-       kfree(s);
-}
-
 static int tracing_resize_saved_cmdlines(unsigned int val)
 {
        struct saved_cmdlines_buffer *s, *savedcmd_temp;
 
-       s = kmalloc(sizeof(*s), GFP_KERNEL);
+       s = allocate_cmdlines_buffer(val);
        if (!s)
                return -ENOMEM;
 
-       if (allocate_cmdlines_buffer(val, s) < 0) {
-               kfree(s);
-               return -ENOMEM;
-       }
-
        preempt_disable();
        arch_spin_lock(&trace_cmdline_lock);
        savedcmd_temp = savedcmd;
index ca224d53bfdcd0df9f6609d3f30a4a6054868136..5bbdbcbbde3cd281f82f3cbc79f72f7a0c3e67ee 100644 (file)
@@ -91,8 +91,8 @@ retry:
        for_each_member(i, type, member) {
                if (!member->name_off) {
                        /* Anonymous union/struct: push it for later use */
-                       type = btf_type_skip_modifiers(btf, member->type, &tid);
-                       if (type && top < BTF_ANON_STACK_MAX) {
+                       if (btf_type_skip_modifiers(btf, member->type, &tid) &&
+                           top < BTF_ANON_STACK_MAX) {
                                anon_stack[top].tid = tid;
                                anon_stack[top++].offset =
                                        cur_offset + member->offset;
index e7af286af4f1ad9d3ac578cb3ce3c58ba3d5ce0b..c82b401a294d961ae75c48f3a164e92f3ad181b1 100644 (file)
@@ -441,8 +441,9 @@ static unsigned int trace_string(struct synth_trace_event *entry,
        if (is_dynamic) {
                union trace_synth_field *data = &entry->fields[*n_u64];
 
+               len = fetch_store_strlen((unsigned long)str_val);
                data->as_dynamic.offset = struct_size(entry, fields, event->n_u64) + data_size;
-               data->as_dynamic.len = fetch_store_strlen((unsigned long)str_val);
+               data->as_dynamic.len = len;
 
                ret = fetch_store_string((unsigned long)str_val, &entry->fields[*n_u64], entry);
 
index 4dc74d73fc1df5af9ee297611865705d44259663..34289f9c67076b2ab81ffc67bd5a518926e59ca6 100644 (file)
@@ -1159,9 +1159,12 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
        if (!(ctx->flags & TPARG_FL_TEVENT) &&
            (strcmp(arg, "$comm") == 0 || strcmp(arg, "$COMM") == 0 ||
             strncmp(arg, "\\\"", 2) == 0)) {
-               /* The type of $comm must be "string", and not an array. */
-               if (parg->count || (t && strcmp(t, "string")))
+               /* The type of $comm must be "string", and not an array type. */
+               if (parg->count || (t && strcmp(t, "string"))) {
+                       trace_probe_log_err(ctx->offset + (t ? (t - arg) : 0),
+                                       NEED_STRING_TYPE);
                        goto out;
+               }
                parg->type = find_fetch_type("string", ctx->flags);
        } else
                parg->type = find_fetch_type(t, ctx->flags);
@@ -1169,18 +1172,6 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
                trace_probe_log_err(ctx->offset + (t ? (t - arg) : 0), BAD_TYPE);
                goto out;
        }
-       parg->offset = *size;
-       *size += parg->type->size * (parg->count ?: 1);
-
-       ret = -ENOMEM;
-       if (parg->count) {
-               len = strlen(parg->type->fmttype) + 6;
-               parg->fmt = kmalloc(len, GFP_KERNEL);
-               if (!parg->fmt)
-                       goto out;
-               snprintf(parg->fmt, len, "%s[%d]", parg->type->fmttype,
-                        parg->count);
-       }
 
        code = tmp = kcalloc(FETCH_INSN_MAX, sizeof(*code), GFP_KERNEL);
        if (!code)
@@ -1204,6 +1195,19 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
                                goto fail;
                }
        }
+       parg->offset = *size;
+       *size += parg->type->size * (parg->count ?: 1);
+
+       if (parg->count) {
+               len = strlen(parg->type->fmttype) + 6;
+               parg->fmt = kmalloc(len, GFP_KERNEL);
+               if (!parg->fmt) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               snprintf(parg->fmt, len, "%s[%d]", parg->type->fmttype,
+                        parg->count);
+       }
 
        ret = -EINVAL;
        /* Store operation */
index 850d9ecb6765a8bd372b214ee6f302e3374ffa93..c1877d0182691c20eba09e60a98d80daf2dd810a 100644 (file)
@@ -515,7 +515,8 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
        C(BAD_HYPHEN,           "Failed to parse single hyphen. Forgot '>'?"),  \
        C(NO_BTF_FIELD,         "This field is not found."),    \
        C(BAD_BTF_TID,          "Failed to get BTF type info."),\
-       C(BAD_TYPE4STR,         "This type does not fit for string."),
+       C(BAD_TYPE4STR,         "This type does not fit for string."),\
+       C(NEED_STRING_TYPE,     "$comm and immediate-string only accepts string type"),
 
 #undef C
 #define C(a, b)                TP_ERR_##a
index 76e60faed892357002868cdf9fb41c76ad4eba54..7b482a26d74196c4505d7b45017ed153c75572fd 100644 (file)
@@ -5786,13 +5786,9 @@ static int workqueue_apply_unbound_cpumask(const cpumask_var_t unbound_cpumask)
        list_for_each_entry(wq, &workqueues, list) {
                if (!(wq->flags & WQ_UNBOUND))
                        continue;
-
                /* creating multiple pwqs breaks ordering guarantee */
-               if (!list_empty(&wq->pwqs)) {
-                       if (wq->flags & __WQ_ORDERED_EXPLICIT)
-                               continue;
-                       wq->flags &= ~__WQ_ORDERED;
-               }
+               if (wq->flags & __WQ_ORDERED)
+                       continue;
 
                ctx = apply_wqattrs_prepare(wq, wq->unbound_attrs, unbound_cpumask);
                if (IS_ERR(ctx)) {
index 54bd558364053c2eb5437e0bf5b94da6cdfba0e1..5fcd48ff0f36a37415c67cf2223cdf7ffeaef794 100644 (file)
@@ -13,5 +13,7 @@
 
 // For internal use only -- registers the kunit_bus.
 int kunit_bus_init(void);
+// For internal use only -- unregisters the kunit_bus.
+void kunit_bus_shutdown(void);
 
 #endif //_KUNIT_DEVICE_IMPL_H
index 074c6dd2e36a7d9e8154a604db7c2a8e4f669921..644a38a1f5b1cf0686a67e7df1a366a3d84e61a6 100644 (file)
@@ -54,6 +54,20 @@ int kunit_bus_init(void)
        return error;
 }
 
+/* Unregister the 'kunit_bus' in case the KUnit module is unloaded. */
+void kunit_bus_shutdown(void)
+{
+       /* Make sure the bus exists before we unregister it. */
+       if (IS_ERR_OR_NULL(kunit_bus_device))
+               return;
+
+       bus_unregister(&kunit_bus_type);
+
+       root_device_unregister(kunit_bus_device);
+
+       kunit_bus_device = NULL;
+}
+
 /* Release a 'fake' KUnit device. */
 static void kunit_device_release(struct device *d)
 {
index 31a5a992e64670f35a9717659f99ca1b385d5f2e..1d1475578515c261fe74b454502f1a2a5ac3bb81 100644 (file)
@@ -928,6 +928,9 @@ static void __exit kunit_exit(void)
 #ifdef CONFIG_MODULES
        unregister_module_notifier(&kunit_mod_nb);
 #endif
+
+       kunit_bus_shutdown();
+
        kunit_debugfs_cleanup();
 }
 module_exit(kunit_exit);
index 010c730ca7fca9b9aab83960a78638046043693f..f3f3436d60a9403eae5b1ef9b091b027881f14fb 100644 (file)
  * seq_buf_init() more than once to reset the seq_buf to start
  * from scratch.
  */
-#include <linux/uaccess.h>
-#include <linux/seq_file.h>
+
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/hex.h>
+#include <linux/minmax.h>
+#include <linux/printk.h>
 #include <linux/seq_buf.h>
+#include <linux/seq_file.h>
+#include <linux/sprintf.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
 
 /**
  * seq_buf_can_fit - can the new data fit in the current buffer?
  * @s: the seq_buf descriptor
  * @len: The length to see if it can fit in the current buffer
  *
- * Returns true if there's enough unused space in the seq_buf buffer
+ * Returns: true if there's enough unused space in the seq_buf buffer
  * to fit the amount of new data according to @len.
  */
 static bool seq_buf_can_fit(struct seq_buf *s, size_t len)
@@ -35,7 +45,7 @@ static bool seq_buf_can_fit(struct seq_buf *s, size_t len)
  * @m: the seq_file descriptor that is the destination
  * @s: the seq_buf descriptor that is the source.
  *
- * Returns zero on success, non zero otherwise
+ * Returns: zero on success, non-zero otherwise.
  */
 int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s)
 {
@@ -50,9 +60,9 @@ int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s)
  * @fmt: printf format string
  * @args: va_list of arguments from a printf() type function
  *
- * Writes a vnprintf() format into the sequencce buffer.
+ * Writes a vnprintf() format into the sequence buffer.
  *
- * Returns zero on success, -1 on overflow.
+ * Returns: zero on success, -1 on overflow.
  */
 int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args)
 {
@@ -78,7 +88,7 @@ int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args)
  *
  * Writes a printf() format into the sequence buffer.
  *
- * Returns zero on success, -1 on overflow.
+ * Returns: zero on success, -1 on overflow.
  */
 int seq_buf_printf(struct seq_buf *s, const char *fmt, ...)
 {
@@ -94,12 +104,12 @@ int seq_buf_printf(struct seq_buf *s, const char *fmt, ...)
 EXPORT_SYMBOL_GPL(seq_buf_printf);
 
 /**
- * seq_buf_do_printk - printk seq_buf line by line
+ * seq_buf_do_printk - printk() seq_buf line by line
  * @s: seq_buf descriptor
  * @lvl: printk level
  *
  * printk()-s a multi-line sequential buffer line by line. The function
- * makes sure that the buffer in @s is nul terminated and safe to read
+ * makes sure that the buffer in @s is NUL-terminated and safe to read
  * as a string.
  */
 void seq_buf_do_printk(struct seq_buf *s, const char *lvl)
@@ -139,7 +149,7 @@ EXPORT_SYMBOL_GPL(seq_buf_do_printk);
  * This function will take the format and the binary array and finish
  * the conversion into the ASCII string within the buffer.
  *
- * Returns zero on success, -1 on overflow.
+ * Returns: zero on success, -1 on overflow.
  */
 int seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary)
 {
@@ -167,7 +177,7 @@ int seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary)
  *
  * Copy a simple string into the sequence buffer.
  *
- * Returns zero on success, -1 on overflow
+ * Returns: zero on success, -1 on overflow.
  */
 int seq_buf_puts(struct seq_buf *s, const char *str)
 {
@@ -196,7 +206,7 @@ EXPORT_SYMBOL_GPL(seq_buf_puts);
  *
  * Copy a single character into the sequence buffer.
  *
- * Returns zero on success, -1 on overflow
+ * Returns: zero on success, -1 on overflow.
  */
 int seq_buf_putc(struct seq_buf *s, unsigned char c)
 {
@@ -212,7 +222,7 @@ int seq_buf_putc(struct seq_buf *s, unsigned char c)
 EXPORT_SYMBOL_GPL(seq_buf_putc);
 
 /**
- * seq_buf_putmem - write raw data into the sequenc buffer
+ * seq_buf_putmem - write raw data into the sequence buffer
  * @s: seq_buf descriptor
  * @mem: The raw memory to copy into the buffer
  * @len: The length of the raw memory to copy (in bytes)
@@ -221,7 +231,7 @@ EXPORT_SYMBOL_GPL(seq_buf_putc);
  * buffer and a strcpy() would not work. Using this function allows
  * for such cases.
  *
- * Returns zero on success, -1 on overflow
+ * Returns: zero on success, -1 on overflow.
  */
 int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len)
 {
@@ -249,7 +259,7 @@ int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len)
  * raw memory into the buffer it writes its ASCII representation of it
  * in hex characters.
  *
- * Returns zero on success, -1 on overflow
+ * Returns: zero on success, -1 on overflow.
  */
 int seq_buf_putmem_hex(struct seq_buf *s, const void *mem,
                       unsigned int len)
@@ -297,7 +307,7 @@ int seq_buf_putmem_hex(struct seq_buf *s, const void *mem,
  *
  * Write a path name into the sequence buffer.
  *
- * Returns the number of written bytes on success, -1 on overflow
+ * Returns: the number of written bytes on success, -1 on overflow.
  */
 int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc)
 {
@@ -332,6 +342,7 @@ int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc)
  * or until it reaches the end of the content in the buffer (@s->len),
  * whichever comes first.
  *
+ * Returns:
  * On success, it returns a positive number of the number of bytes
  * it copied.
  *
@@ -382,11 +393,11 @@ int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, size_t start, int cnt)
  * linebuf size is maximal length for one line.
  * 32 * 3 - maximum bytes per line, each printed into 2 chars + 1 for
  *     separating space
- * 2 - spaces separating hex dump and ascii representation
- * 32 - ascii representation
+ * 2 - spaces separating hex dump and ASCII representation
+ * 32 - ASCII representation
  * 1 - terminating '\0'
  *
- * Returns zero on success, -1 on overflow
+ * Returns: zero on success, -1 on overflow.
  */
 int seq_buf_hex_dump(struct seq_buf *s, const char *prefix_str, int prefix_type,
                     int rowsize, int groupsize,
index 1e3447bccdb14d126b3c108fd27ab652b5a3a94f..e039d05304dd9ca52da735962c0ef951fb448ec5 100644 (file)
@@ -436,7 +436,6 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
        INIT_LIST_HEAD(&wb->work_list);
        INIT_DELAYED_WORK(&wb->dwork, wb_workfn);
        INIT_DELAYED_WORK(&wb->bw_dwork, wb_update_bandwidth_workfn);
-       wb->dirty_sleep = jiffies;
 
        err = fprop_local_init_percpu(&wb->completions, gfp);
        if (err)
@@ -921,6 +920,7 @@ int bdi_init(struct backing_dev_info *bdi)
        INIT_LIST_HEAD(&bdi->bdi_list);
        INIT_LIST_HEAD(&bdi->wb_list);
        init_waitqueue_head(&bdi->wb_waitq);
+       bdi->last_bdp_sleep = jiffies;
 
        return cgwb_bdi_init(bdi);
 }
index 8dbaac6e5c2d05dc4bc7c2b7545be26d508afd9a..dd2fb512700920803b10621b82ffaa88bff30a92 100644 (file)
@@ -2194,7 +2194,7 @@ static void damos_tried_regions_init_upd_status(
                sysfs_regions->upd_timeout_jiffies = jiffies +
                        2 * usecs_to_jiffies(scheme->apply_interval_us ?
                                        scheme->apply_interval_us :
-                                       ctx->attrs.sample_interval);
+                                       ctx->attrs.aggr_interval);
        }
 }
 
index 912155a94ed5871c1805f33ec624c7c7c1ee28c8..cfa5e7288261189cb8242e5a0367fe6ffeebca12 100644 (file)
@@ -429,6 +429,7 @@ restart:
                if (++batch_count == SWAP_CLUSTER_MAX) {
                        batch_count = 0;
                        if (need_resched()) {
+                               arch_leave_lazy_mmu_mode();
                                pte_unmap_unlock(start_pte, ptl);
                                cond_resched();
                                goto restart;
index 46d8d02114cfeeda78049fa986d29ac1b324d7f3..1ed40f9d3a277ec8912c77326c5527a259a96c47 100644 (file)
@@ -621,6 +621,15 @@ static inline int memcg_events_index(enum vm_event_item idx)
 }
 
 struct memcg_vmstats_percpu {
+       /* Stats updates since the last flush */
+       unsigned int                    stats_updates;
+
+       /* Cached pointers for fast iteration in memcg_rstat_updated() */
+       struct memcg_vmstats_percpu     *parent;
+       struct memcg_vmstats            *vmstats;
+
+       /* The above should fit a single cacheline for memcg_rstat_updated() */
+
        /* Local (CPU and cgroup) page state & events */
        long                    state[MEMCG_NR_STAT];
        unsigned long           events[NR_MEMCG_EVENTS];
@@ -632,10 +641,7 @@ struct memcg_vmstats_percpu {
        /* Cgroup1: threshold notifications & softlimit tree updates */
        unsigned long           nr_page_events;
        unsigned long           targets[MEM_CGROUP_NTARGETS];
-
-       /* Stats updates since the last flush */
-       unsigned int            stats_updates;
-};
+} ____cacheline_aligned;
 
 struct memcg_vmstats {
        /* Aggregated (CPU and subtree) page state & events */
@@ -698,36 +704,35 @@ static void memcg_stats_unlock(void)
 }
 
 
-static bool memcg_should_flush_stats(struct mem_cgroup *memcg)
+static bool memcg_vmstats_needs_flush(struct memcg_vmstats *vmstats)
 {
-       return atomic64_read(&memcg->vmstats->stats_updates) >
+       return atomic64_read(&vmstats->stats_updates) >
                MEMCG_CHARGE_BATCH * num_online_cpus();
 }
 
 static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val)
 {
+       struct memcg_vmstats_percpu *statc;
        int cpu = smp_processor_id();
-       unsigned int x;
 
        if (!val)
                return;
 
        cgroup_rstat_updated(memcg->css.cgroup, cpu);
-
-       for (; memcg; memcg = parent_mem_cgroup(memcg)) {
-               x = __this_cpu_add_return(memcg->vmstats_percpu->stats_updates,
-                                         abs(val));
-
-               if (x < MEMCG_CHARGE_BATCH)
+       statc = this_cpu_ptr(memcg->vmstats_percpu);
+       for (; statc; statc = statc->parent) {
+               statc->stats_updates += abs(val);
+               if (statc->stats_updates < MEMCG_CHARGE_BATCH)
                        continue;
 
                /*
                 * If @memcg is already flush-able, increasing stats_updates is
                 * redundant. Avoid the overhead of the atomic update.
                 */
-               if (!memcg_should_flush_stats(memcg))
-                       atomic64_add(x, &memcg->vmstats->stats_updates);
-               __this_cpu_write(memcg->vmstats_percpu->stats_updates, 0);
+               if (!memcg_vmstats_needs_flush(statc->vmstats))
+                       atomic64_add(statc->stats_updates,
+                                    &statc->vmstats->stats_updates);
+               statc->stats_updates = 0;
        }
 }
 
@@ -756,7 +761,7 @@ void mem_cgroup_flush_stats(struct mem_cgroup *memcg)
        if (!memcg)
                memcg = root_mem_cgroup;
 
-       if (memcg_should_flush_stats(memcg))
+       if (memcg_vmstats_needs_flush(memcg->vmstats))
                do_flush_stats(memcg);
 }
 
@@ -770,7 +775,7 @@ void mem_cgroup_flush_stats_ratelimited(struct mem_cgroup *memcg)
 static void flush_memcg_stats_dwork(struct work_struct *w)
 {
        /*
-        * Deliberately ignore memcg_should_flush_stats() here so that flushing
+        * Deliberately ignore memcg_vmstats_needs_flush() here so that flushing
         * in latency-sensitive paths is as cheap as possible.
         */
        do_flush_stats(root_mem_cgroup);
@@ -5477,10 +5482,11 @@ static void mem_cgroup_free(struct mem_cgroup *memcg)
        __mem_cgroup_free(memcg);
 }
 
-static struct mem_cgroup *mem_cgroup_alloc(void)
+static struct mem_cgroup *mem_cgroup_alloc(struct mem_cgroup *parent)
 {
+       struct memcg_vmstats_percpu *statc, *pstatc;
        struct mem_cgroup *memcg;
-       int node;
+       int node, cpu;
        int __maybe_unused i;
        long error = -ENOMEM;
 
@@ -5504,6 +5510,14 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
        if (!memcg->vmstats_percpu)
                goto fail;
 
+       for_each_possible_cpu(cpu) {
+               if (parent)
+                       pstatc = per_cpu_ptr(parent->vmstats_percpu, cpu);
+               statc = per_cpu_ptr(memcg->vmstats_percpu, cpu);
+               statc->parent = parent ? pstatc : NULL;
+               statc->vmstats = memcg->vmstats;
+       }
+
        for_each_node(node)
                if (alloc_mem_cgroup_per_node_info(memcg, node))
                        goto fail;
@@ -5549,7 +5563,7 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
        struct mem_cgroup *memcg, *old_memcg;
 
        old_memcg = set_active_memcg(parent);
-       memcg = mem_cgroup_alloc();
+       memcg = mem_cgroup_alloc(parent);
        set_active_memcg(old_memcg);
        if (IS_ERR(memcg))
                return ERR_CAST(memcg);
index 636280d04008d8550dda8f9aa12acf6da5d92848..9349948f1abfd120977706bbda23456999f057bc 100644 (file)
@@ -1377,6 +1377,9 @@ void ClearPageHWPoisonTakenOff(struct page *page)
  */
 static inline bool HWPoisonHandlable(struct page *page, unsigned long flags)
 {
+       if (PageSlab(page))
+               return false;
+
        /* Soft offline could migrate non-LRU movable pages */
        if ((flags & MF_SOFT_OFFLINE) && __PageMovable(page))
                return true;
index 89bcae0b224d6d43b4720c5c71a6c528e683bafb..15f8b10ea17c4f28e857009372f50bfd774001b9 100644 (file)
@@ -5478,7 +5478,7 @@ static inline bool get_mmap_lock_carefully(struct mm_struct *mm, struct pt_regs
                return true;
 
        if (regs && !user_mode(regs)) {
-               unsigned long ip = instruction_pointer(regs);
+               unsigned long ip = exception_ip(regs);
                if (!search_exception_tables(ip))
                        return false;
        }
@@ -5503,7 +5503,7 @@ static inline bool upgrade_mmap_lock_carefully(struct mm_struct *mm, struct pt_r
 {
        mmap_read_unlock(mm);
        if (regs && !user_mode(regs)) {
-               unsigned long ip = instruction_pointer(regs);
+               unsigned long ip = exception_ip(regs);
                if (!search_exception_tables(ip))
                        return false;
        }
index 02147b61712bc9e3536061bb33d3f54f2e5db463..3f255534986a2fda07e2d35187bb385f64749c5c 100644 (file)
@@ -1921,7 +1921,7 @@ pause:
                        break;
                }
                __set_current_state(TASK_KILLABLE);
-               wb->dirty_sleep = now;
+               bdi->last_bdp_sleep = jiffies;
                io_schedule_timeout(pause);
 
                current->dirty_paused_when = now + pause;
index 75fcf1f783bc567d1a916c85fb7abddc169f7fb5..7cf7d43842590ccd99bf37795918a7054b61a8c4 100644 (file)
@@ -902,8 +902,8 @@ static int move_present_pte(struct mm_struct *mm,
 
        double_pt_lock(dst_ptl, src_ptl);
 
-       if (!pte_same(*src_pte, orig_src_pte) ||
-           !pte_same(*dst_pte, orig_dst_pte)) {
+       if (!pte_same(ptep_get(src_pte), orig_src_pte) ||
+           !pte_same(ptep_get(dst_pte), orig_dst_pte)) {
                err = -EAGAIN;
                goto out;
        }
@@ -946,8 +946,8 @@ static int move_swap_pte(struct mm_struct *mm,
 
        double_pt_lock(dst_ptl, src_ptl);
 
-       if (!pte_same(*src_pte, orig_src_pte) ||
-           !pte_same(*dst_pte, orig_dst_pte)) {
+       if (!pte_same(ptep_get(src_pte), orig_src_pte) ||
+           !pte_same(ptep_get(dst_pte), orig_dst_pte)) {
                double_pt_unlock(dst_ptl, src_ptl);
                return -EAGAIN;
        }
@@ -1016,7 +1016,7 @@ retry:
        }
 
        spin_lock(dst_ptl);
-       orig_dst_pte = *dst_pte;
+       orig_dst_pte = ptep_get(dst_pte);
        spin_unlock(dst_ptl);
        if (!pte_none(orig_dst_pte)) {
                err = -EEXIST;
@@ -1024,7 +1024,7 @@ retry:
        }
 
        spin_lock(src_ptl);
-       orig_src_pte = *src_pte;
+       orig_src_pte = ptep_get(src_pte);
        spin_unlock(src_ptl);
        if (pte_none(orig_src_pte)) {
                if (!(mode & UFFDIO_MOVE_MODE_ALLOW_SRC_HOLES))
@@ -1054,7 +1054,7 @@ retry:
                         * page isn't freed under us
                         */
                        spin_lock(src_ptl);
-                       if (!pte_same(orig_src_pte, *src_pte)) {
+                       if (!pte_same(orig_src_pte, ptep_get(src_pte))) {
                                spin_unlock(src_ptl);
                                err = -EAGAIN;
                                goto out;
index ca25b676048ea6d0b399661e9ebca137585f8dbd..350dd2fc815994739d2012e0bcf483445350bb88 100644 (file)
@@ -536,10 +536,6 @@ static struct zpool *zswap_find_zpool(struct zswap_entry *entry)
  */
 static void zswap_free_entry(struct zswap_entry *entry)
 {
-       if (entry->objcg) {
-               obj_cgroup_uncharge_zswap(entry->objcg, entry->length);
-               obj_cgroup_put(entry->objcg);
-       }
        if (!entry->length)
                atomic_dec(&zswap_same_filled_pages);
        else {
@@ -548,6 +544,10 @@ static void zswap_free_entry(struct zswap_entry *entry)
                atomic_dec(&entry->pool->nr_stored);
                zswap_pool_put(entry->pool);
        }
+       if (entry->objcg) {
+               obj_cgroup_uncharge_zswap(entry->objcg, entry->length);
+               obj_cgroup_put(entry->objcg);
+       }
        zswap_entry_cache_free(entry);
        atomic_dec(&zswap_stored_pages);
        zswap_update_total_size();
@@ -895,10 +895,8 @@ static enum lru_status shrink_memcg_cb(struct list_head *item, struct list_lru_o
                 * into the warmer region. We should terminate shrinking (if we're in the dynamic
                 * shrinker context).
                 */
-               if (writeback_result == -EEXIST && encountered_page_in_swapcache) {
-                       ret = LRU_SKIP;
+               if (writeback_result == -EEXIST && encountered_page_in_swapcache)
                        *encountered_page_in_swapcache = true;
-               }
 
                goto put_unlock;
        }
index 7b3341cef926ef37ce84c7dd09301c84c0a103c6..850d4a185f55f87f70a5e0a5112d1ab20d3eb070 100644 (file)
@@ -179,4 +179,5 @@ static void __exit lowpan_module_exit(void)
 module_init(lowpan_module_init);
 module_exit(lowpan_module_exit);
 
+MODULE_DESCRIPTION("IPv6 over Low-Power Wireless Personal Area Network core module");
 MODULE_LICENSE("GPL");
index 033871e718a34f7430929f862fcbcc886d933622..324e3ab96bb393d815901bb2d221ef6e18cf25e4 100644 (file)
@@ -1532,4 +1532,5 @@ static void __exit atm_mpoa_cleanup(void)
 module_init(atm_mpoa_init);
 module_exit(atm_mpoa_cleanup);
 
+MODULE_DESCRIPTION("Multi-Protocol Over ATM (MPOA) driver");
 MODULE_LICENSE("GPL");
index 16af1a7f80f60e18b5526c973f66e98821786a78..31a93cae5111b50d54e10a061a9e235e81a1da1c 100644 (file)
@@ -86,7 +86,7 @@ struct j1939_priv {
        unsigned int tp_max_packet_size;
 
        /* lock for j1939_socks list */
-       spinlock_t j1939_socks_lock;
+       rwlock_t j1939_socks_lock;
        struct list_head j1939_socks;
 
        struct kref rx_kref;
@@ -301,6 +301,7 @@ struct j1939_sock {
 
        int ifindex;
        struct j1939_addr addr;
+       spinlock_t filters_lock;
        struct j1939_filter *filters;
        int nfilters;
        pgn_t pgn_rx_filter;
index ecff1c947d683b2f3e4eeff144f39a8f5ff5de1a..a6fb89fa62785121f9edc42308b052142fda5fdd 100644 (file)
@@ -274,7 +274,7 @@ struct j1939_priv *j1939_netdev_start(struct net_device *ndev)
                return ERR_PTR(-ENOMEM);
 
        j1939_tp_init(priv);
-       spin_lock_init(&priv->j1939_socks_lock);
+       rwlock_init(&priv->j1939_socks_lock);
        INIT_LIST_HEAD(&priv->j1939_socks);
 
        mutex_lock(&j1939_netdev_lock);
index 14c43166323393541bc102f47a311c79199a2acd..305dd72c844c70f1589f14fcb668bd46b92ff6f2 100644 (file)
@@ -80,16 +80,16 @@ static void j1939_jsk_add(struct j1939_priv *priv, struct j1939_sock *jsk)
        jsk->state |= J1939_SOCK_BOUND;
        j1939_priv_get(priv);
 
-       spin_lock_bh(&priv->j1939_socks_lock);
+       write_lock_bh(&priv->j1939_socks_lock);
        list_add_tail(&jsk->list, &priv->j1939_socks);
-       spin_unlock_bh(&priv->j1939_socks_lock);
+       write_unlock_bh(&priv->j1939_socks_lock);
 }
 
 static void j1939_jsk_del(struct j1939_priv *priv, struct j1939_sock *jsk)
 {
-       spin_lock_bh(&priv->j1939_socks_lock);
+       write_lock_bh(&priv->j1939_socks_lock);
        list_del_init(&jsk->list);
-       spin_unlock_bh(&priv->j1939_socks_lock);
+       write_unlock_bh(&priv->j1939_socks_lock);
 
        j1939_priv_put(priv);
        jsk->state &= ~J1939_SOCK_BOUND;
@@ -262,12 +262,17 @@ static bool j1939_sk_match_dst(struct j1939_sock *jsk,
 static bool j1939_sk_match_filter(struct j1939_sock *jsk,
                                  const struct j1939_sk_buff_cb *skcb)
 {
-       const struct j1939_filter *f = jsk->filters;
-       int nfilter = jsk->nfilters;
+       const struct j1939_filter *f;
+       int nfilter;
+
+       spin_lock_bh(&jsk->filters_lock);
+
+       f = jsk->filters;
+       nfilter = jsk->nfilters;
 
        if (!nfilter)
                /* receive all when no filters are assigned */
-               return true;
+               goto filter_match_found;
 
        for (; nfilter; ++f, --nfilter) {
                if ((skcb->addr.pgn & f->pgn_mask) != f->pgn)
@@ -276,9 +281,15 @@ static bool j1939_sk_match_filter(struct j1939_sock *jsk,
                        continue;
                if ((skcb->addr.src_name & f->name_mask) != f->name)
                        continue;
-               return true;
+               goto filter_match_found;
        }
+
+       spin_unlock_bh(&jsk->filters_lock);
        return false;
+
+filter_match_found:
+       spin_unlock_bh(&jsk->filters_lock);
+       return true;
 }
 
 static bool j1939_sk_recv_match_one(struct j1939_sock *jsk,
@@ -329,13 +340,13 @@ bool j1939_sk_recv_match(struct j1939_priv *priv, struct j1939_sk_buff_cb *skcb)
        struct j1939_sock *jsk;
        bool match = false;
 
-       spin_lock_bh(&priv->j1939_socks_lock);
+       read_lock_bh(&priv->j1939_socks_lock);
        list_for_each_entry(jsk, &priv->j1939_socks, list) {
                match = j1939_sk_recv_match_one(jsk, skcb);
                if (match)
                        break;
        }
-       spin_unlock_bh(&priv->j1939_socks_lock);
+       read_unlock_bh(&priv->j1939_socks_lock);
 
        return match;
 }
@@ -344,11 +355,11 @@ void j1939_sk_recv(struct j1939_priv *priv, struct sk_buff *skb)
 {
        struct j1939_sock *jsk;
 
-       spin_lock_bh(&priv->j1939_socks_lock);
+       read_lock_bh(&priv->j1939_socks_lock);
        list_for_each_entry(jsk, &priv->j1939_socks, list) {
                j1939_sk_recv_one(jsk, skb);
        }
-       spin_unlock_bh(&priv->j1939_socks_lock);
+       read_unlock_bh(&priv->j1939_socks_lock);
 }
 
 static void j1939_sk_sock_destruct(struct sock *sk)
@@ -401,6 +412,7 @@ static int j1939_sk_init(struct sock *sk)
        atomic_set(&jsk->skb_pending, 0);
        spin_lock_init(&jsk->sk_session_queue_lock);
        INIT_LIST_HEAD(&jsk->sk_session_queue);
+       spin_lock_init(&jsk->filters_lock);
 
        /* j1939_sk_sock_destruct() depends on SOCK_RCU_FREE flag */
        sock_set_flag(sk, SOCK_RCU_FREE);
@@ -703,9 +715,11 @@ static int j1939_sk_setsockopt(struct socket *sock, int level, int optname,
                }
 
                lock_sock(&jsk->sk);
+               spin_lock_bh(&jsk->filters_lock);
                ofilters = jsk->filters;
                jsk->filters = filters;
                jsk->nfilters = count;
+               spin_unlock_bh(&jsk->filters_lock);
                release_sock(&jsk->sk);
                kfree(ofilters);
                return 0;
@@ -1080,12 +1094,12 @@ void j1939_sk_errqueue(struct j1939_session *session,
        }
 
        /* spread RX notifications to all sockets subscribed to this session */
-       spin_lock_bh(&priv->j1939_socks_lock);
+       read_lock_bh(&priv->j1939_socks_lock);
        list_for_each_entry(jsk, &priv->j1939_socks, list) {
                if (j1939_sk_recv_match_one(jsk, &session->skcb))
                        __j1939_sk_errqueue(session, &jsk->sk, type);
        }
-       spin_unlock_bh(&priv->j1939_socks_lock);
+       read_unlock_bh(&priv->j1939_socks_lock);
 };
 
 void j1939_sk_send_loop_abort(struct sock *sk, int err)
@@ -1273,7 +1287,7 @@ void j1939_sk_netdev_event_netdown(struct j1939_priv *priv)
        struct j1939_sock *jsk;
        int error_code = ENETDOWN;
 
-       spin_lock_bh(&priv->j1939_socks_lock);
+       read_lock_bh(&priv->j1939_socks_lock);
        list_for_each_entry(jsk, &priv->j1939_socks, list) {
                jsk->sk.sk_err = error_code;
                if (!sock_flag(&jsk->sk, SOCK_DEAD))
@@ -1281,7 +1295,7 @@ void j1939_sk_netdev_event_netdown(struct j1939_priv *priv)
 
                j1939_sk_queue_drop_all(priv, jsk, error_code);
        }
-       spin_unlock_bh(&priv->j1939_socks_lock);
+       read_unlock_bh(&priv->j1939_socks_lock);
 }
 
 static int j1939_sk_no_ioctlcmd(struct socket *sock, unsigned int cmd,
index f9a50d7f0d204639f821835d341bb87c13a80333..0cb61c76b9b87da0746294cb371bc62defec0f81 100644 (file)
@@ -160,8 +160,9 @@ static size_t sizeof_footer(struct ceph_connection *con)
 static void prepare_message_data(struct ceph_msg *msg, u32 data_len)
 {
        /* Initialize data cursor if it's not a sparse read */
-       if (!msg->sparse_read)
-               ceph_msg_data_cursor_init(&msg->cursor, msg, data_len);
+       u64 len = msg->sparse_read_total ? : data_len;
+
+       ceph_msg_data_cursor_init(&msg->cursor, msg, len);
 }
 
 /*
@@ -991,7 +992,7 @@ static inline int read_partial_message_section(struct ceph_connection *con,
        return read_partial_message_chunk(con, section, sec_len, crc);
 }
 
-static int read_sparse_msg_extent(struct ceph_connection *con, u32 *crc)
+static int read_partial_sparse_msg_extent(struct ceph_connection *con, u32 *crc)
 {
        struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor;
        bool do_bounce = ceph_test_opt(from_msgr(con->msgr), RXBOUNCE);
@@ -1026,7 +1027,7 @@ static int read_sparse_msg_extent(struct ceph_connection *con, u32 *crc)
        return 1;
 }
 
-static int read_sparse_msg_data(struct ceph_connection *con)
+static int read_partial_sparse_msg_data(struct ceph_connection *con)
 {
        struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor;
        bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC);
@@ -1036,31 +1037,31 @@ static int read_sparse_msg_data(struct ceph_connection *con)
        if (do_datacrc)
                crc = con->in_data_crc;
 
-       do {
+       while (cursor->total_resid) {
                if (con->v1.in_sr_kvec.iov_base)
                        ret = read_partial_message_chunk(con,
                                                         &con->v1.in_sr_kvec,
                                                         con->v1.in_sr_len,
                                                         &crc);
                else if (cursor->sr_resid > 0)
-                       ret = read_sparse_msg_extent(con, &crc);
-
-               if (ret <= 0) {
-                       if (do_datacrc)
-                               con->in_data_crc = crc;
-                       return ret;
-               }
+                       ret = read_partial_sparse_msg_extent(con, &crc);
+               if (ret <= 0)
+                       break;
 
                memset(&con->v1.in_sr_kvec, 0, sizeof(con->v1.in_sr_kvec));
                ret = con->ops->sparse_read(con, cursor,
                                (char **)&con->v1.in_sr_kvec.iov_base);
+               if (ret <= 0) {
+                       ret = ret ? ret : 1;  /* must return > 0 to indicate success */
+                       break;
+               }
                con->v1.in_sr_len = ret;
-       } while (ret > 0);
+       }
 
        if (do_datacrc)
                con->in_data_crc = crc;
 
-       return ret < 0 ? ret : 1;  /* must return > 0 to indicate success */
+       return ret;
 }
 
 static int read_partial_msg_data(struct ceph_connection *con)
@@ -1253,8 +1254,8 @@ static int read_partial_message(struct ceph_connection *con)
                if (!m->num_data_items)
                        return -EIO;
 
-               if (m->sparse_read)
-                       ret = read_sparse_msg_data(con);
+               if (m->sparse_read_total)
+                       ret = read_partial_sparse_msg_data(con);
                else if (ceph_test_opt(from_msgr(con->msgr), RXBOUNCE))
                        ret = read_partial_msg_data_bounce(con);
                else
index f8ec60e1aba3a112aaa024c235f0117297b9bf70..a0ca5414b333df92b3aa0085a95b928cdc0609a5 100644 (file)
@@ -1128,7 +1128,7 @@ static int decrypt_tail(struct ceph_connection *con)
        struct sg_table enc_sgt = {};
        struct sg_table sgt = {};
        struct page **pages = NULL;
-       bool sparse = con->in_msg->sparse_read;
+       bool sparse = !!con->in_msg->sparse_read_total;
        int dpos = 0;
        int tail_len;
        int ret;
@@ -2060,7 +2060,7 @@ static int prepare_read_tail_plain(struct ceph_connection *con)
        }
 
        if (data_len(msg)) {
-               if (msg->sparse_read)
+               if (msg->sparse_read_total)
                        con->v2.in_state = IN_S_PREPARE_SPARSE_DATA;
                else
                        con->v2.in_state = IN_S_PREPARE_READ_DATA;
index 625622016f5761e36bccc3f7a239e265039ce95d..9d078b37fe0b9b085894be86db17053227de9a18 100644 (file)
@@ -5510,7 +5510,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
        }
 
        m = ceph_msg_get(req->r_reply);
-       m->sparse_read = (bool)srlen;
+       m->sparse_read_total = srlen;
 
        dout("get_reply tid %lld %p\n", tid, m);
 
@@ -5777,11 +5777,8 @@ static int prep_next_sparse_read(struct ceph_connection *con,
        }
 
        if (o->o_sparse_op_idx < 0) {
-               u64 srlen = sparse_data_requested(req);
-
-               dout("%s: [%d] starting new sparse read req. srlen=0x%llx\n",
-                    __func__, o->o_osd, srlen);
-               ceph_msg_data_cursor_init(cursor, con->in_msg, srlen);
+               dout("%s: [%d] starting new sparse read req\n",
+                    __func__, o->o_osd);
        } else {
                u64 end;
 
@@ -5857,8 +5854,8 @@ static int osd_sparse_read(struct ceph_connection *con,
        struct ceph_osd *o = con->private;
        struct ceph_sparse_read *sr = &o->o_sparse_read;
        u32 count = sr->sr_count;
-       u64 eoff, elen;
-       int ret;
+       u64 eoff, elen, len = 0;
+       int i, ret;
 
        switch (sr->sr_state) {
        case CEPH_SPARSE_READ_HDR:
@@ -5903,8 +5900,20 @@ next_op:
                convert_extent_map(sr);
                ret = sizeof(sr->sr_datalen);
                *pbuf = (char *)&sr->sr_datalen;
-               sr->sr_state = CEPH_SPARSE_READ_DATA;
+               sr->sr_state = CEPH_SPARSE_READ_DATA_PRE;
                break;
+       case CEPH_SPARSE_READ_DATA_PRE:
+               /* Convert sr_datalen to host-endian */
+               sr->sr_datalen = le32_to_cpu((__force __le32)sr->sr_datalen);
+               for (i = 0; i < count; i++)
+                       len += sr->sr_extent[i].len;
+               if (sr->sr_datalen != len) {
+                       pr_warn_ratelimited("data len %u != extent len %llu\n",
+                                           sr->sr_datalen, len);
+                       return -EREMOTEIO;
+               }
+               sr->sr_state = CEPH_SPARSE_READ_DATA;
+               fallthrough;
        case CEPH_SPARSE_READ_DATA:
                if (sr->sr_index >= count) {
                        sr->sr_state = CEPH_SPARSE_READ_HDR;
index 103d46fa0eeb34af20b2d74b79f38e7424e25155..a8b625abe242c657dca8cd0188c236553757c6b2 100644 (file)
@@ -751,7 +751,7 @@ size_t memcpy_to_iter_csum(void *iter_to, size_t progress,
                           size_t len, void *from, void *priv2)
 {
        __wsum *csum = priv2;
-       __wsum next = csum_partial_copy_nocheck(from, iter_to, len);
+       __wsum next = csum_partial_copy_nocheck(from + progress, iter_to, len);
 
        *csum = csum_block_add(*csum, next, progress);
        return 0;
index cb2dab0feee0abe758479a7a001342bf6613df08..73a0219730075e666c4f11f668a50dbf9f9afa97 100644 (file)
@@ -336,7 +336,7 @@ int netdev_name_node_alt_create(struct net_device *dev, const char *name)
                return -ENOMEM;
        netdev_name_node_add(net, name_node);
        /* The node that holds dev->name acts as a head of per-device list. */
-       list_add_tail(&name_node->list, &dev->name_node->list);
+       list_add_tail_rcu(&name_node->list, &dev->name_node->list);
 
        return 0;
 }
@@ -11652,11 +11652,12 @@ static void __init net_dev_struct_check(void)
        CACHELINE_ASSERT_GROUP_SIZE(struct net_device, net_device_read_tx, 160);
 
        /* TXRX read-mostly hotpath */
+       CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, lstats);
        CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, flags);
        CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, hard_header_len);
        CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, features);
        CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, ip6_ptr);
-       CACHELINE_ASSERT_GROUP_SIZE(struct net_device, net_device_read_txrx, 30);
+       CACHELINE_ASSERT_GROUP_SIZE(struct net_device, net_device_read_txrx, 38);
 
        /* RX read-mostly hotpath */
        CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, ptype_specific);
index f6f29eb03ec277a1ea17ccc220fa7624bf6db092..9c4f427f3a5057b52ec05405e8b15b8ca2246b4b 100644 (file)
@@ -1020,14 +1020,17 @@ static size_t rtnl_xdp_size(void)
 static size_t rtnl_prop_list_size(const struct net_device *dev)
 {
        struct netdev_name_node *name_node;
-       size_t size;
+       unsigned int cnt = 0;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(name_node, &dev->name_node->list, list)
+               cnt++;
+       rcu_read_unlock();
 
-       if (list_empty(&dev->name_node->list))
+       if (!cnt)
                return 0;
-       size = nla_total_size(0);
-       list_for_each_entry(name_node, &dev->name_node->list, list)
-               size += nla_total_size(ALTIFNAMSIZ);
-       return size;
+
+       return nla_total_size(0) + cnt * nla_total_size(ALTIFNAMSIZ);
 }
 
 static size_t rtnl_proto_down_size(const struct net_device *dev)
index 4275a2bc6d8e062052a88503b731d9599ca55d2a..6a58342752b4690d1f13d19eb94ee1d44b9cda61 100644 (file)
@@ -46,7 +46,7 @@ struct devlink_rel {
                u32 obj_index;
                devlink_rel_notify_cb_t *notify_cb;
                devlink_rel_cleanup_cb_t *cleanup_cb;
-               struct work_struct notify_work;
+               struct delayed_work notify_work;
        } nested_in;
 };
 
@@ -70,7 +70,7 @@ static void __devlink_rel_put(struct devlink_rel *rel)
 static void devlink_rel_nested_in_notify_work(struct work_struct *work)
 {
        struct devlink_rel *rel = container_of(work, struct devlink_rel,
-                                              nested_in.notify_work);
+                                              nested_in.notify_work.work);
        struct devlink *devlink;
 
        devlink = devlinks_xa_get(rel->nested_in.devlink_index);
@@ -96,13 +96,13 @@ rel_put:
        return;
 
 reschedule_work:
-       schedule_work(&rel->nested_in.notify_work);
+       schedule_delayed_work(&rel->nested_in.notify_work, 1);
 }
 
 static void devlink_rel_nested_in_notify_work_schedule(struct devlink_rel *rel)
 {
        __devlink_rel_get(rel);
-       schedule_work(&rel->nested_in.notify_work);
+       schedule_delayed_work(&rel->nested_in.notify_work, 0);
 }
 
 static struct devlink_rel *devlink_rel_alloc(void)
@@ -123,8 +123,8 @@ static struct devlink_rel *devlink_rel_alloc(void)
        }
 
        refcount_set(&rel->refcount, 1);
-       INIT_WORK(&rel->nested_in.notify_work,
-                 &devlink_rel_nested_in_notify_work);
+       INIT_DELAYED_WORK(&rel->nested_in.notify_work,
+                         &devlink_rel_nested_in_notify_work);
        return rel;
 }
 
index 16ed7bfd29e4fbf39e204278950834b9e69b9f97..34fd1d9b2db861de15f7ce68828abedbf6bc771c 100644 (file)
@@ -471,7 +471,10 @@ static void handshake_req_destroy_test1(struct kunit *test)
        handshake_req_cancel(sock->sk);
 
        /* Act */
-       fput(filp);
+       /* Ensure the close/release/put process has run to
+        * completion before checking the result.
+        */
+       __fput_sync(filp);
 
        /* Assert */
        KUNIT_EXPECT_PTR_EQ(test, handshake_req_destroy_test, req);
index 4e635dd3d3c8cca0aee00fa508368dc3d8965b93..a5a820ee2026691afdd5ca3255962b5116fca290 100644 (file)
@@ -1628,10 +1628,12 @@ EXPORT_SYMBOL(inet_current_timestamp);
 
 int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
-       if (sk->sk_family == AF_INET)
+       unsigned int family = READ_ONCE(sk->sk_family);
+
+       if (family == AF_INET)
                return ip_recv_error(sk, msg, len, addr_len);
 #if IS_ENABLED(CONFIG_IPV6)
-       if (sk->sk_family == AF_INET6)
+       if (family == AF_INET6)
                return pingv6_ops.ipv6_recv_error(sk, msg, len, addr_len);
 #endif
        return -EINVAL;
index a2e6e1fdf82be44c15daefa2a423967ccd8999f7..64aec3dff8ec85135a8d14e5618900927eb59959 100644 (file)
@@ -597,5 +597,6 @@ static void __exit ah4_fini(void)
 
 module_init(ah4_init);
 module_exit(ah4_fini);
+MODULE_DESCRIPTION("IPv4 AH transformation library");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_AH);
index 4ccfc104f13a517ec15e5b609502708c289e3b57..4dd9e50406720cfc90d280f61e4616d6a2e58d3c 100644 (file)
@@ -1247,5 +1247,6 @@ static void __exit esp4_fini(void)
 
 module_init(esp4_init);
 module_exit(esp4_fini);
+MODULE_DESCRIPTION("IPv4 ESP transformation library");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_ESP);
index 5169c3c72cffe49cef613e69889d139db867ff74..6b9cf5a24c19ff06634f7841141b8a30639b8d17 100644 (file)
@@ -1793,6 +1793,7 @@ static void __exit ipgre_fini(void)
 
 module_init(ipgre_init);
 module_exit(ipgre_fini);
+MODULE_DESCRIPTION("IPv4 GRE tunnels over IP library");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_RTNL_LINK("gre");
 MODULE_ALIAS_RTNL_LINK("gretap");
index 41537d18eecfd6e1163aacc35e047c22468e04e6..67d846622365e8da9c2295f76943a504d16b066f 100644 (file)
@@ -972,8 +972,8 @@ static int __ip_append_data(struct sock *sk,
        unsigned int maxfraglen, fragheaderlen, maxnonfragsize;
        int csummode = CHECKSUM_NONE;
        struct rtable *rt = (struct rtable *)cork->dst;
+       bool paged, hold_tskey, extra_uref = false;
        unsigned int wmem_alloc_delta = 0;
-       bool paged, extra_uref = false;
        u32 tskey = 0;
 
        skb = skb_peek_tail(queue);
@@ -982,10 +982,6 @@ static int __ip_append_data(struct sock *sk,
        mtu = cork->gso_size ? IP_MAX_MTU : cork->fragsize;
        paged = !!cork->gso_size;
 
-       if (cork->tx_flags & SKBTX_ANY_TSTAMP &&
-           READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID)
-               tskey = atomic_inc_return(&sk->sk_tskey) - 1;
-
        hh_len = LL_RESERVED_SPACE(rt->dst.dev);
 
        fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
@@ -1052,6 +1048,11 @@ static int __ip_append_data(struct sock *sk,
 
        cork->length += length;
 
+       hold_tskey = cork->tx_flags & SKBTX_ANY_TSTAMP &&
+                    READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID;
+       if (hold_tskey)
+               tskey = atomic_inc_return(&sk->sk_tskey) - 1;
+
        /* So, what's going on in the loop below?
         *
         * We use calculated fragment length to generate chained skb,
@@ -1274,6 +1275,8 @@ error:
        cork->length -= length;
        IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
        refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
+       if (hold_tskey)
+               atomic_dec(&sk->sk_tskey);
        return err;
 }
 
index beeae624c412d752bd5ee5d459a88f57640445e9..a4513ffb66cbb74c14112bbc4c1d36d02e7f659b 100644 (file)
@@ -1298,4 +1298,5 @@ void ip_tunnel_setup(struct net_device *dev, unsigned int net_id)
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_setup);
 
+MODULE_DESCRIPTION("IPv4 tunnel implementation library");
 MODULE_LICENSE("GPL");
index 586b1b3e35b805d46158531ae8e7b49122abbaa7..80ccd6661aa32f2b60a720a18deec26e9e2cc18d 100644 (file)
@@ -332,7 +332,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
        };
        skb_reset_network_header(skb);
 
-       csum = csum_partial(icmp6h, len, 0);
+       csum = skb_checksum(skb, skb_transport_offset(skb), len, 0);
        icmp6h->icmp6_cksum = csum_ipv6_magic(&nip6h->saddr, &nip6h->daddr, len,
                                              IPPROTO_ICMPV6, csum);
 
index 9ab9b3ebe0cd1a9e95f489d98c5a3d89c7c0edf6..d1d6bb28ed6e95c6e9c247bf1df1b27287bc8328 100644 (file)
@@ -721,6 +721,7 @@ static void __exit vti_fini(void)
 
 module_init(vti_init);
 module_exit(vti_fini);
+MODULE_DESCRIPTION("Virtual (secure) IP tunneling library");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_RTNL_LINK("vti");
 MODULE_ALIAS_NETDEV("ip_vti0");
index 27b8f83c6ea200314f41a29ecfea494b9ddef2ca..03afa3871efc53b5af543e7d53283be69a02f818 100644 (file)
@@ -658,6 +658,7 @@ static void __exit ipip_fini(void)
 
 module_init(ipip_init);
 module_exit(ipip_fini);
+MODULE_DESCRIPTION("IP/IP protocol decoder library");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_RTNL_LINK("ipip");
 MODULE_ALIAS_NETDEV("tunl0");
index 7e2481b9eae1b791e1ec65f39efa41837a9fcbd3..c82dc42f57c65df112f79080ff407cd98d11ce68 100644 (file)
@@ -4615,7 +4615,8 @@ static void __init tcp_struct_check(void)
        CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_read_txrx, prr_out);
        CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_read_txrx, lost_out);
        CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_read_txrx, sacked_out);
-       CACHELINE_ASSERT_GROUP_SIZE(struct tcp_sock, tcp_sock_read_txrx, 31);
+       CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_read_txrx, scaling_ratio);
+       CACHELINE_ASSERT_GROUP_SIZE(struct tcp_sock, tcp_sock_read_txrx, 32);
 
        /* RX read-mostly hotpath cache lines */
        CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_read_rx, copied_seq);
index 5048c47c79b2848a1b42032dceb4884f43cd4748..4c1f836aae38b7a75b912db9e2cdc84ccfc48e56 100644 (file)
@@ -294,4 +294,5 @@ static void __exit tunnel4_fini(void)
 
 module_init(tunnel4_init);
 module_exit(tunnel4_fini);
+MODULE_DESCRIPTION("IPv4 XFRM tunnel library");
 MODULE_LICENSE("GPL");
index a87defb2b16729886d20fcec53cea939c7fea4b7..860aff5f85990252607651c173a6d84006e5afe1 100644 (file)
@@ -253,4 +253,5 @@ struct rtable *udp_tunnel_dst_lookup(struct sk_buff *skb,
 }
 EXPORT_SYMBOL_GPL(udp_tunnel_dst_lookup);
 
+MODULE_DESCRIPTION("IPv4 Foo over UDP tunnel driver");
 MODULE_LICENSE("GPL");
index 8489fa10658377eb0942943e537a453d781f4520..8cb266af139311b48af474fc19eff32c6d8b5e37 100644 (file)
@@ -114,5 +114,6 @@ static void __exit ipip_fini(void)
 
 module_init(ipip_init);
 module_exit(ipip_fini);
+MODULE_DESCRIPTION("IPv4 XFRM tunnel driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP);
index 2016e90e6e1d21a49696c9933f1b77320cc71953..eb474f0987ae016b9d800e9f83d70d73171b21d2 100644 (file)
@@ -800,5 +800,6 @@ static void __exit ah6_fini(void)
 module_init(ah6_init);
 module_exit(ah6_fini);
 
+MODULE_DESCRIPTION("IPv6 AH transformation helpers");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH);
index 2cc1a45742d823a793d95140910942fb83e7f331..6e6efe026cdcc2feab9a1f18fb784042b586f045 100644 (file)
@@ -1301,5 +1301,6 @@ static void __exit esp6_fini(void)
 module_init(esp6_init);
 module_exit(esp6_fini);
 
+MODULE_DESCRIPTION("IPv6 ESP transformation helpers");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);
index a722a43dd668581cf4efb08ee5ab8410e5adebb7..31b86fe661aa6cd94fb5d8848900406c2db110e3 100644 (file)
@@ -1424,11 +1424,11 @@ static int __ip6_append_data(struct sock *sk,
        bool zc = false;
        u32 tskey = 0;
        struct rt6_info *rt = (struct rt6_info *)cork->dst;
+       bool paged, hold_tskey, extra_uref = false;
        struct ipv6_txoptions *opt = v6_cork->opt;
        int csummode = CHECKSUM_NONE;
        unsigned int maxnonfragsize, headersize;
        unsigned int wmem_alloc_delta = 0;
-       bool paged, extra_uref = false;
 
        skb = skb_peek_tail(queue);
        if (!skb) {
@@ -1440,10 +1440,6 @@ static int __ip6_append_data(struct sock *sk,
        mtu = cork->gso_size ? IP6_MAX_MTU : cork->fragsize;
        orig_mtu = mtu;
 
-       if (cork->tx_flags & SKBTX_ANY_TSTAMP &&
-           READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID)
-               tskey = atomic_inc_return(&sk->sk_tskey) - 1;
-
        hh_len = LL_RESERVED_SPACE(rt->dst.dev);
 
        fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
@@ -1538,6 +1534,11 @@ emsgsize:
                        flags &= ~MSG_SPLICE_PAGES;
        }
 
+       hold_tskey = cork->tx_flags & SKBTX_ANY_TSTAMP &&
+                    READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID;
+       if (hold_tskey)
+               tskey = atomic_inc_return(&sk->sk_tskey) - 1;
+
        /*
         * Let's try using as much space as possible.
         * Use MTU if total length of the message fits into the MTU.
@@ -1794,6 +1795,8 @@ error:
        cork->length -= length;
        IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
        refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
+       if (hold_tskey)
+               atomic_dec(&sk->sk_tskey);
        return err;
 }
 
index a7bf0327b380be90bfdcc2182ed3a4296a0e814f..c99053189ea8a13be63927290576655e8da0c0fb 100644 (file)
@@ -182,4 +182,5 @@ struct dst_entry *udp_tunnel6_dst_lookup(struct sk_buff *skb,
 }
 EXPORT_SYMBOL_GPL(udp_tunnel6_dst_lookup);
 
+MODULE_DESCRIPTION("IPv6 Foo over UDP tunnel driver");
 MODULE_LICENSE("GPL");
index 83d2a8be263fb7bdd0cbe820168b1aac9a4336b2..6a16a5bd0d910bca55a87c55580cbd1cae71bede 100644 (file)
@@ -405,6 +405,7 @@ static void __exit mip6_fini(void)
 module_init(mip6_init);
 module_exit(mip6_fini);
 
+MODULE_DESCRIPTION("IPv6 Mobility driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_DSTOPTS);
 MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ROUTING);
index cc24cefdb85c0944c03c019b1c4214302d18e2c8..5e9f625b76e36b9a61c6c2db0b4163e78dca549a 100644 (file)
@@ -1956,6 +1956,7 @@ xfrm_tunnel_failed:
 
 module_init(sit_init);
 module_exit(sit_cleanup);
+MODULE_DESCRIPTION("IPv6-in-IPv4 tunnel SIT driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_RTNL_LINK("sit");
 MODULE_ALIAS_NETDEV("sit0");
index 00e8d8b1c9a75fa1a820ac85eba91e3e24750c01..dc4ea9b11794e800eb027855e59a56fa6197df0b 100644 (file)
@@ -302,4 +302,5 @@ static void __exit tunnel6_fini(void)
 
 module_init(tunnel6_init);
 module_exit(tunnel6_fini);
+MODULE_DESCRIPTION("IP-in-IPv6 tunnel driver");
 MODULE_LICENSE("GPL");
index 1323f2f6928e2abf277e9ce7bd06025cd0049031..f6cb94f82cc3a2b40717a0c4406801dd26ac18c3 100644 (file)
@@ -401,5 +401,6 @@ static void __exit xfrm6_tunnel_fini(void)
 
 module_init(xfrm6_tunnel_init);
 module_exit(xfrm6_tunnel_fini);
+MODULE_DESCRIPTION("IPv6 XFRM tunnel driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_IPV6);
index d68d01804dc7bcf7df78ff6968518298fe9d596a..f79fb99271ed84b8fe981a2b34a25b6abcf9d8e0 100644 (file)
@@ -3924,5 +3924,6 @@ out_unregister_key_proto:
 
 module_init(ipsec_pfkey_init);
 module_exit(ipsec_pfkey_exit);
+MODULE_DESCRIPTION("PF_KEY socket helpers");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NETPROTO(PF_KEY);
index 489dd97f51724a86053a9c4e9269487c4c7e928b..327682995c9260c9c7498ff9b322ecf5d59c6717 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2024 Intel Corporation
  */
 
 #include <linux/ieee80211.h>
@@ -987,7 +987,8 @@ static int
 ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
                                     struct cfg80211_unsol_bcast_probe_resp *params,
                                     struct ieee80211_link_data *link,
-                                    struct ieee80211_bss_conf *link_conf)
+                                    struct ieee80211_bss_conf *link_conf,
+                                    u64 *changed)
 {
        struct unsol_bcast_probe_resp_data *new, *old = NULL;
 
@@ -1011,7 +1012,8 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
                RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL);
        }
 
-       return BSS_CHANGED_UNSOL_BCAST_PROBE_RESP;
+       *changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP;
+       return 0;
 }
 
 static int ieee80211_set_ftm_responder_params(
@@ -1450,10 +1452,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 
        err = ieee80211_set_unsol_bcast_probe_resp(sdata,
                                                   &params->unsol_bcast_probe_resp,
-                                                  link, link_conf);
+                                                  link, link_conf, &changed);
        if (err < 0)
                goto error;
-       changed |= err;
 
        err = drv_start_ap(sdata->local, sdata, link_conf);
        if (err) {
@@ -1525,10 +1526,9 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
 
        err = ieee80211_set_unsol_bcast_probe_resp(sdata,
                                                   &params->unsol_bcast_probe_resp,
-                                                  link, link_conf);
+                                                  link, link_conf, &changed);
        if (err < 0)
                return err;
-       changed |= err;
 
        if (beacon->he_bss_color_valid &&
            beacon->he_bss_color.enabled != link_conf->he_bss_color.enabled) {
@@ -1869,6 +1869,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
                                              sband->band);
        }
 
+       ieee80211_sta_set_rx_nss(link_sta);
+
        return ret;
 }
 
index dce5606ed66da5a31a476aec16bb55412e1e72cc..68596ef78b15ee9596f6f81e8dd2d2f82c1d56cd 100644 (file)
@@ -997,8 +997,8 @@ static void add_link_files(struct ieee80211_link_data *link,
        }
 }
 
-void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata,
-                                 bool mld_vif)
+static void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata,
+                                        bool mld_vif)
 {
        char buf[10+IFNAMSIZ];
 
index b226b1aae88a5d4205c0206b351b63e6ee54c2a2..a02ec0a413f61468dded52076fbfef9a35da17b0 100644 (file)
@@ -11,8 +11,6 @@
 #include "ieee80211_i.h"
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata,
-                                 bool mld_vif);
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
 void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata);
 void ieee80211_debugfs_recreate_netdev(struct ieee80211_sub_if_data *sdata,
@@ -24,9 +22,6 @@ void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link);
 void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link);
 void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link);
 #else
-static inline void ieee80211_debugfs_add_netdev(
-       struct ieee80211_sub_if_data *sdata, bool mld_vif)
-{}
 static inline void ieee80211_debugfs_remove_netdev(
        struct ieee80211_sub_if_data *sdata)
 {}
index e4e7c0b38cb6efcbb65786d071f436e09c7bf322..11c4caa4748e4038a2c758e34ae8dbf762e8159e 100644 (file)
@@ -1783,7 +1783,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
        /* need to do this after the switch so vif.type is correct */
        ieee80211_link_setup(&sdata->deflink);
 
-       ieee80211_debugfs_add_netdev(sdata, false);
+       ieee80211_debugfs_recreate_netdev(sdata, false);
 }
 
 static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
index 073105deb42481f2792a33fa0341d509f7a95017..2022a26eb8811492ef8029de9e89dfd4bbb5f101 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2023 Intel Corporation
+ * Copyright (C) 2018 - 2024 Intel Corporation
  */
 
 #include <linux/delay.h>
@@ -2918,6 +2918,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
        /* other links will be destroyed */
        sdata->deflink.u.mgd.bss = NULL;
+       sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
 
        netif_carrier_off(sdata->dev);
 
@@ -5045,9 +5046,6 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        if (!link)
                return 0;
 
-       /* will change later if needed */
-       link->smps_mode = IEEE80211_SMPS_OFF;
-
        /*
         * If this fails (possibly due to channel context sharing
         * on incompatible channels, e.g. 80+80 and 160 sharing the
@@ -7096,6 +7094,7 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link)
        link->u.mgd.p2p_noa_index = -1;
        link->u.mgd.conn_flags = 0;
        link->conf->bssid = link->u.mgd.bssid;
+       link->smps_mode = IEEE80211_SMPS_OFF;
 
        wiphy_work_init(&link->u.mgd.request_smps_work,
                        ieee80211_request_smps_mgd_work);
@@ -7309,6 +7308,75 @@ out_err:
        return err;
 }
 
+static bool ieee80211_mgd_csa_present(struct ieee80211_sub_if_data *sdata,
+                                     const struct cfg80211_bss_ies *ies,
+                                     u8 cur_channel, bool ignore_ecsa)
+{
+       const struct element *csa_elem, *ecsa_elem;
+       struct ieee80211_channel_sw_ie *csa = NULL;
+       struct ieee80211_ext_chansw_ie *ecsa = NULL;
+
+       if (!ies)
+               return false;
+
+       csa_elem = cfg80211_find_elem(WLAN_EID_CHANNEL_SWITCH,
+                                     ies->data, ies->len);
+       if (csa_elem && csa_elem->datalen == sizeof(*csa))
+               csa = (void *)csa_elem->data;
+
+       ecsa_elem = cfg80211_find_elem(WLAN_EID_EXT_CHANSWITCH_ANN,
+                                      ies->data, ies->len);
+       if (ecsa_elem && ecsa_elem->datalen == sizeof(*ecsa))
+               ecsa = (void *)ecsa_elem->data;
+
+       if (csa && csa->count == 0)
+               csa = NULL;
+       if (csa && !csa->mode && csa->new_ch_num == cur_channel)
+               csa = NULL;
+
+       if (ecsa && ecsa->count == 0)
+               ecsa = NULL;
+       if (ecsa && !ecsa->mode && ecsa->new_ch_num == cur_channel)
+               ecsa = NULL;
+
+       if (ignore_ecsa && ecsa) {
+               sdata_info(sdata,
+                          "Ignoring ECSA in probe response - was considered stuck!\n");
+               return csa;
+       }
+
+       return csa || ecsa;
+}
+
+static bool ieee80211_mgd_csa_in_process(struct ieee80211_sub_if_data *sdata,
+                                        struct cfg80211_bss *bss)
+{
+       u8 cur_channel;
+       bool ret;
+
+       cur_channel = ieee80211_frequency_to_channel(bss->channel->center_freq);
+
+       rcu_read_lock();
+       if (ieee80211_mgd_csa_present(sdata,
+                                     rcu_dereference(bss->beacon_ies),
+                                     cur_channel, false)) {
+               ret = true;
+               goto out;
+       }
+
+       if (ieee80211_mgd_csa_present(sdata,
+                                     rcu_dereference(bss->proberesp_ies),
+                                     cur_channel, bss->proberesp_ecsa_stuck)) {
+               ret = true;
+               goto out;
+       }
+
+       ret = false;
+out:
+       rcu_read_unlock();
+       return ret;
+}
+
 /* config hooks */
 int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
                       struct cfg80211_auth_request *req)
@@ -7317,7 +7385,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_mgd_auth_data *auth_data;
        struct ieee80211_link_data *link;
-       const struct element *csa_elem, *ecsa_elem;
        u16 auth_alg;
        int err;
        bool cont_auth;
@@ -7360,21 +7427,10 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->assoc_data)
                return -EBUSY;
 
-       rcu_read_lock();
-       csa_elem = ieee80211_bss_get_elem(req->bss, WLAN_EID_CHANNEL_SWITCH);
-       ecsa_elem = ieee80211_bss_get_elem(req->bss,
-                                          WLAN_EID_EXT_CHANSWITCH_ANN);
-       if ((csa_elem &&
-            csa_elem->datalen == sizeof(struct ieee80211_channel_sw_ie) &&
-            ((struct ieee80211_channel_sw_ie *)csa_elem->data)->count != 0) ||
-           (ecsa_elem &&
-            ecsa_elem->datalen == sizeof(struct ieee80211_ext_chansw_ie) &&
-            ((struct ieee80211_ext_chansw_ie *)ecsa_elem->data)->count != 0)) {
-               rcu_read_unlock();
+       if (ieee80211_mgd_csa_in_process(sdata, req->bss)) {
                sdata_info(sdata, "AP is in CSA process, reject auth\n");
                return -EINVAL;
        }
-       rcu_read_unlock();
 
        auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
                            req->ie_len, GFP_KERNEL);
@@ -7684,7 +7740,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_mgd_assoc_data *assoc_data;
-       const struct element *ssid_elem, *csa_elem, *ecsa_elem;
+       const struct element *ssid_elem;
        struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg;
        ieee80211_conn_flags_t conn_flags = 0;
        struct ieee80211_link_data *link;
@@ -7707,23 +7763,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 
        cbss = req->link_id < 0 ? req->bss : req->links[req->link_id].bss;
 
-       rcu_read_lock();
-       ssid_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_SSID);
-       if (!ssid_elem || ssid_elem->datalen > sizeof(assoc_data->ssid)) {
-               rcu_read_unlock();
+       if (ieee80211_mgd_csa_in_process(sdata, cbss)) {
+               sdata_info(sdata, "AP is in CSA process, reject assoc\n");
                kfree(assoc_data);
                return -EINVAL;
        }
 
-       csa_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_CHANNEL_SWITCH);
-       ecsa_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_EXT_CHANSWITCH_ANN);
-       if ((csa_elem &&
-            csa_elem->datalen == sizeof(struct ieee80211_channel_sw_ie) &&
-            ((struct ieee80211_channel_sw_ie *)csa_elem->data)->count != 0) ||
-           (ecsa_elem &&
-            ecsa_elem->datalen == sizeof(struct ieee80211_ext_chansw_ie) &&
-            ((struct ieee80211_ext_chansw_ie *)ecsa_elem->data)->count != 0)) {
-               sdata_info(sdata, "AP is in CSA process, reject assoc\n");
+       rcu_read_lock();
+       ssid_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_SSID);
+       if (!ssid_elem || ssid_elem->datalen > sizeof(assoc_data->ssid)) {
                rcu_read_unlock();
                kfree(assoc_data);
                return -EINVAL;
@@ -7998,8 +8046,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 
                rcu_read_lock();
                beacon_ies = rcu_dereference(req->bss->beacon_ies);
-
-               if (beacon_ies) {
+               if (!beacon_ies) {
                        /*
                         * Wait up to one beacon interval ...
                         * should this be more if we miss one?
@@ -8080,6 +8127,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                ieee80211_report_disconnect(sdata, frame_buf,
                                            sizeof(frame_buf), true,
                                            req->reason_code, false);
+               drv_mgd_complete_tx(sdata->local, sdata, &info);
                return 0;
        }
 
index 645355e5f1bc7baba435db18c0c8d8243a4649c6..f9d5842601fa9433ba0303f3b6572129b3e2f9fe 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
  * Copyright 2016-2017  Intel Deutschland GmbH
- * Copyright (C) 2018-2023 Intel Corporation
+ * Copyright (C) 2018-2024 Intel Corporation
  */
 
 #include <linux/if_arp.h>
@@ -237,14 +237,18 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
 }
 
 static bool ieee80211_scan_accept_presp(struct ieee80211_sub_if_data *sdata,
+                                       struct ieee80211_channel *channel,
                                        u32 scan_flags, const u8 *da)
 {
        if (!sdata)
                return false;
-       /* accept broadcast for OCE */
-       if (scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP &&
-           is_broadcast_ether_addr(da))
+
+       /* accept broadcast on 6 GHz and for OCE */
+       if (is_broadcast_ether_addr(da) &&
+           (channel->band == NL80211_BAND_6GHZ ||
+            scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP))
                return true;
+
        if (scan_flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
                return true;
        return ether_addr_equal(da, sdata->vif.addr);
@@ -293,6 +297,12 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
                wiphy_delayed_work_queue(local->hw.wiphy, &local->scan_work, 0);
        }
 
+       channel = ieee80211_get_channel_khz(local->hw.wiphy,
+                                           ieee80211_rx_status_to_khz(rx_status));
+
+       if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
+               return;
+
        if (ieee80211_is_probe_resp(mgmt->frame_control)) {
                struct cfg80211_scan_request *scan_req;
                struct cfg80211_sched_scan_request *sched_scan_req;
@@ -310,19 +320,15 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
                /* ignore ProbeResp to foreign address or non-bcast (OCE)
                 * unless scanning with randomised address
                 */
-               if (!ieee80211_scan_accept_presp(sdata1, scan_req_flags,
+               if (!ieee80211_scan_accept_presp(sdata1, channel,
+                                                scan_req_flags,
                                                 mgmt->da) &&
-                   !ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags,
+                   !ieee80211_scan_accept_presp(sdata2, channel,
+                                                sched_scan_req_flags,
                                                 mgmt->da))
                        return;
        }
 
-       channel = ieee80211_get_channel_khz(local->hw.wiphy,
-                                       ieee80211_rx_status_to_khz(rx_status));
-
-       if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
-               return;
-
        bss = ieee80211_bss_info_update(local, rx_status,
                                        mgmt, skb->len,
                                        channel);
index 68a48abc72876c4abaa8cf4c95d7c2793dc07813..6fbb15b65902c754ea4c2487a40d4ce0ed38634a 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2024 Intel Corporation
  *
  * Transmit and frame generation functions.
  */
@@ -3100,10 +3100,11 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
                        /* DA SA BSSID */
                        build.da_offs = offsetof(struct ieee80211_hdr, addr1);
                        build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
+                       rcu_read_lock();
                        link = rcu_dereference(sdata->link[tdls_link_id]);
-                       if (WARN_ON_ONCE(!link))
-                               break;
-                       memcpy(hdr->addr3, link->u.mgd.bssid, ETH_ALEN);
+                       if (!WARN_ON_ONCE(!link))
+                               memcpy(hdr->addr3, link->u.mgd.bssid, ETH_ALEN);
+                       rcu_read_unlock();
                        build.hdr_len = 24;
                        break;
                }
@@ -3926,6 +3927,7 @@ begin:
                        goto begin;
 
                skb = __skb_dequeue(&tx.skbs);
+               info = IEEE80211_SKB_CB(skb);
 
                if (!skb_queue_empty(&tx.skbs)) {
                        spin_lock_bh(&fq->lock);
@@ -3970,7 +3972,7 @@ begin:
        }
 
 encap_out:
-       IEEE80211_SKB_CB(skb)->control.vif = vif;
+       info->control.vif = vif;
 
        if (tx.sta &&
            wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
index a05c5b971789c796658a04e0a41a3748fdce75da..3a8612309137312f88dfe6bad79ac854fe76fcc1 100644 (file)
@@ -23,8 +23,6 @@ void ieee80211_check_wbrf_support(struct ieee80211_local *local)
                return;
 
        local->wbrf_supported = acpi_amd_wbrf_supported_producer(dev);
-       dev_dbg(dev, "WBRF is %s supported\n",
-               local->wbrf_supported ? "" : "not");
 }
 
 static void get_chan_freq_boundary(u32 center_freq, u32 bandwidth, u64 *start, u64 *end)
index 74698582a2859e4d6ea40abaf8d0f31943e0d128..ad28da655f8bcc75e4ea05d4de2e2ab073ebc2c5 100644 (file)
@@ -59,13 +59,12 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subf
        mptcp_data_unlock(sk);
 }
 
-void mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
-                                  const struct mptcp_options_received *mp_opt)
+void __mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
+                                    const struct mptcp_options_received *mp_opt)
 {
        struct sock *sk = (struct sock *)msk;
        struct sk_buff *skb;
 
-       mptcp_data_lock(sk);
        skb = skb_peek_tail(&sk->sk_receive_queue);
        if (skb) {
                WARN_ON_ONCE(MPTCP_SKB_CB(skb)->end_seq);
@@ -77,5 +76,4 @@ void mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_
        }
 
        pr_debug("msk=%p ack_seq=%llx", msk, msk->ack_seq);
-       mptcp_data_unlock(sk);
 }
index d2527d189a799319c068a5b76a5816cc7a905861..e3e96a49f92296aed056137a815f0e2a30b8407c 100644 (file)
@@ -962,9 +962,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
                /* subflows are fully established as soon as we get any
                 * additional ack, including ADD_ADDR.
                 */
-               subflow->fully_established = 1;
-               WRITE_ONCE(msk->fully_established, true);
-               goto check_notify;
+               goto set_fully_established;
        }
 
        /* If the first established packet does not contain MP_CAPABLE + data
@@ -986,7 +984,10 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
 set_fully_established:
        if (unlikely(!READ_ONCE(msk->pm.server_side)))
                pr_warn_once("bogus mpc option on established client sk");
-       mptcp_subflow_fully_established(subflow, mp_opt);
+
+       mptcp_data_lock((struct sock *)msk);
+       __mptcp_subflow_fully_established(msk, subflow, mp_opt);
+       mptcp_data_unlock((struct sock *)msk);
 
 check_notify:
        /* if the subflow is not already linked into the conn_list, we can't
index efecbe3cf41533324a5df71da39f775dd2078ca6..4f3901d5b8ef8bd75759cae5de602c5112355b53 100644 (file)
@@ -130,10 +130,21 @@ int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
 int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
                                    struct mptcp_addr_info *skc)
 {
-       struct mptcp_pm_addr_entry new_entry;
+       struct mptcp_pm_addr_entry *entry = NULL, *e, new_entry;
        __be16 msk_sport =  ((struct inet_sock *)
                             inet_sk((struct sock *)msk))->inet_sport;
 
+       spin_lock_bh(&msk->pm.lock);
+       list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) {
+               if (mptcp_addresses_equal(&e->addr, skc, false)) {
+                       entry = e;
+                       break;
+               }
+       }
+       spin_unlock_bh(&msk->pm.lock);
+       if (entry)
+               return entry->addr.id;
+
        memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry));
        new_entry.addr = *skc;
        new_entry.addr.id = 0;
index 028e8b473626f122db6e3e664414b2f0447fae69..8ef2927ebca297bf60d51fae91732e09562fd496 100644 (file)
@@ -1505,8 +1505,11 @@ static void mptcp_update_post_push(struct mptcp_sock *msk,
 
 void mptcp_check_and_set_pending(struct sock *sk)
 {
-       if (mptcp_send_head(sk))
-               mptcp_sk(sk)->push_pending |= BIT(MPTCP_PUSH_PENDING);
+       if (mptcp_send_head(sk)) {
+               mptcp_data_lock(sk);
+               mptcp_sk(sk)->cb_flags |= BIT(MPTCP_PUSH_PENDING);
+               mptcp_data_unlock(sk);
+       }
 }
 
 static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
@@ -1960,6 +1963,9 @@ static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied)
        if (copied <= 0)
                return;
 
+       if (!msk->rcvspace_init)
+               mptcp_rcv_space_init(msk, msk->first);
+
        msk->rcvq_space.copied += copied;
 
        mstamp = div_u64(tcp_clock_ns(), NSEC_PER_USEC);
@@ -3142,7 +3148,6 @@ static int mptcp_disconnect(struct sock *sk, int flags)
        mptcp_destroy_common(msk, MPTCP_CF_FASTCLOSE);
        WRITE_ONCE(msk->flags, 0);
        msk->cb_flags = 0;
-       msk->push_pending = 0;
        msk->recovery = false;
        msk->can_ack = false;
        msk->fully_established = false;
@@ -3158,6 +3163,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)
        msk->bytes_received = 0;
        msk->bytes_sent = 0;
        msk->bytes_retrans = 0;
+       msk->rcvspace_init = 0;
 
        WRITE_ONCE(sk->sk_shutdown, 0);
        sk_error_report(sk);
@@ -3180,6 +3186,7 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk,
 {
        struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
        struct sock *nsk = sk_clone_lock(sk, GFP_ATOMIC);
+       struct mptcp_subflow_context *subflow;
        struct mptcp_sock *msk;
 
        if (!nsk)
@@ -3220,7 +3227,8 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk,
 
        /* The msk maintain a ref to each subflow in the connections list */
        WRITE_ONCE(msk->first, ssk);
-       list_add(&mptcp_subflow_ctx(ssk)->node, &msk->conn_list);
+       subflow = mptcp_subflow_ctx(ssk);
+       list_add(&subflow->node, &msk->conn_list);
        sock_hold(ssk);
 
        /* new mpc subflow takes ownership of the newly
@@ -3235,6 +3243,9 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk,
        __mptcp_propagate_sndbuf(nsk, ssk);
 
        mptcp_rcv_space_init(msk, ssk);
+
+       if (mp_opt->suboptions & OPTION_MPTCP_MPC_ACK)
+               __mptcp_subflow_fully_established(msk, subflow, mp_opt);
        bh_unlock_sock(nsk);
 
        /* note: the newly allocated socket refcount is 2 now */
@@ -3245,6 +3256,7 @@ void mptcp_rcv_space_init(struct mptcp_sock *msk, const struct sock *ssk)
 {
        const struct tcp_sock *tp = tcp_sk(ssk);
 
+       msk->rcvspace_init = 1;
        msk->rcvq_space.copied = 0;
        msk->rcvq_space.rtt_us = 0;
 
@@ -3255,8 +3267,6 @@ void mptcp_rcv_space_init(struct mptcp_sock *msk, const struct sock *ssk)
                                      TCP_INIT_CWND * tp->advmss);
        if (msk->rcvq_space.space == 0)
                msk->rcvq_space.space = TCP_INIT_CWND * TCP_MSS_DEFAULT;
-
-       WRITE_ONCE(msk->wnd_end, msk->snd_nxt + tcp_sk(ssk)->snd_wnd);
 }
 
 void mptcp_destroy_common(struct mptcp_sock *msk, unsigned int flags)
@@ -3330,8 +3340,7 @@ static void mptcp_release_cb(struct sock *sk)
        struct mptcp_sock *msk = mptcp_sk(sk);
 
        for (;;) {
-               unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED) |
-                                     msk->push_pending;
+               unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED);
                struct list_head join_list;
 
                if (!flags)
@@ -3347,7 +3356,6 @@ static void mptcp_release_cb(struct sock *sk)
                 *    datapath acquires the msk socket spinlock while helding
                 *    the subflow socket lock
                 */
-               msk->push_pending = 0;
                msk->cb_flags &= ~flags;
                spin_unlock_bh(&sk->sk_lock.slock);
 
@@ -3475,13 +3483,8 @@ void mptcp_finish_connect(struct sock *ssk)
         * accessing the field below
         */
        WRITE_ONCE(msk->local_key, subflow->local_key);
-       WRITE_ONCE(msk->write_seq, subflow->idsn + 1);
-       WRITE_ONCE(msk->snd_nxt, msk->write_seq);
-       WRITE_ONCE(msk->snd_una, msk->write_seq);
 
        mptcp_pm_new_connection(msk, ssk, 0);
-
-       mptcp_rcv_space_init(msk, ssk);
 }
 
 void mptcp_sock_graft(struct sock *sk, struct socket *parent)
index 3517f2d24a226ff0be1adec800044810f1aa31c6..ed50f2015dc389d035e919a5d509e12899e22687 100644 (file)
@@ -286,7 +286,6 @@ struct mptcp_sock {
        int             rmem_released;
        unsigned long   flags;
        unsigned long   cb_flags;
-       unsigned long   push_pending;
        bool            recovery;               /* closing subflow write queue reinjected */
        bool            can_ack;
        bool            fully_established;
@@ -305,7 +304,8 @@ struct mptcp_sock {
                        nodelay:1,
                        fastopening:1,
                        in_accept_queue:1,
-                       free_first:1;
+                       free_first:1,
+                       rcvspace_init:1;
        struct work_struct work;
        struct sk_buff  *ooo_last_skb;
        struct rb_root  out_of_order_queue;
@@ -622,8 +622,9 @@ unsigned int mptcp_stale_loss_cnt(const struct net *net);
 unsigned int mptcp_close_timeout(const struct sock *sk);
 int mptcp_get_pm_type(const struct net *net);
 const char *mptcp_get_scheduler(const struct net *net);
-void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
-                                    const struct mptcp_options_received *mp_opt);
+void __mptcp_subflow_fully_established(struct mptcp_sock *msk,
+                                      struct mptcp_subflow_context *subflow,
+                                      const struct mptcp_options_received *mp_opt);
 bool __mptcp_retransmit_pending_data(struct sock *sk);
 void mptcp_check_and_set_pending(struct sock *sk);
 void __mptcp_push_pending(struct sock *sk, unsigned int flags);
@@ -952,8 +953,8 @@ void mptcp_event_pm_listener(const struct sock *ssk,
                             enum mptcp_event_type event);
 bool mptcp_userspace_pm_active(const struct mptcp_sock *msk);
 
-void mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
-                                  const struct mptcp_options_received *mp_opt);
+void __mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
+                                    const struct mptcp_options_received *mp_opt);
 void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subflow,
                                              struct request_sock *req);
 
@@ -1128,7 +1129,8 @@ static inline bool subflow_simultaneous_connect(struct sock *sk)
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
 
-       return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_FIN_WAIT1) &&
+       return (1 << sk->sk_state) &
+              (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | TCPF_CLOSING) &&
               is_active_ssk(subflow) &&
               !subflow->conn_finished;
 }
index 0dcb721c89d193e8943aa414610fcf4284d51f38..c34ecadee1200a4804ea732df0b3d8a7b4f6e174 100644 (file)
@@ -421,29 +421,26 @@ static bool subflow_use_different_dport(struct mptcp_sock *msk, const struct soc
 
 void __mptcp_sync_state(struct sock *sk, int state)
 {
+       struct mptcp_subflow_context *subflow;
        struct mptcp_sock *msk = mptcp_sk(sk);
+       struct sock *ssk = msk->first;
+
+       subflow = mptcp_subflow_ctx(ssk);
+       __mptcp_propagate_sndbuf(sk, ssk);
+       if (!msk->rcvspace_init)
+               mptcp_rcv_space_init(msk, ssk);
 
-       __mptcp_propagate_sndbuf(sk, msk->first);
        if (sk->sk_state == TCP_SYN_SENT) {
+               /* subflow->idsn is always available is TCP_SYN_SENT state,
+                * even for the FASTOPEN scenarios
+                */
+               WRITE_ONCE(msk->write_seq, subflow->idsn + 1);
+               WRITE_ONCE(msk->snd_nxt, msk->write_seq);
                mptcp_set_state(sk, state);
                sk->sk_state_change(sk);
        }
 }
 
-static void mptcp_propagate_state(struct sock *sk, struct sock *ssk)
-{
-       struct mptcp_sock *msk = mptcp_sk(sk);
-
-       mptcp_data_lock(sk);
-       if (!sock_owned_by_user(sk)) {
-               __mptcp_sync_state(sk, ssk->sk_state);
-       } else {
-               msk->pending_state = ssk->sk_state;
-               __set_bit(MPTCP_SYNC_STATE, &msk->cb_flags);
-       }
-       mptcp_data_unlock(sk);
-}
-
 static void subflow_set_remote_key(struct mptcp_sock *msk,
                                   struct mptcp_subflow_context *subflow,
                                   const struct mptcp_options_received *mp_opt)
@@ -465,6 +462,31 @@ static void subflow_set_remote_key(struct mptcp_sock *msk,
        atomic64_set(&msk->rcv_wnd_sent, subflow->iasn);
 }
 
+static void mptcp_propagate_state(struct sock *sk, struct sock *ssk,
+                                 struct mptcp_subflow_context *subflow,
+                                 const struct mptcp_options_received *mp_opt)
+{
+       struct mptcp_sock *msk = mptcp_sk(sk);
+
+       mptcp_data_lock(sk);
+       if (mp_opt) {
+               /* Options are available only in the non fallback cases
+                * avoid updating rx path fields otherwise
+                */
+               WRITE_ONCE(msk->snd_una, subflow->idsn + 1);
+               WRITE_ONCE(msk->wnd_end, subflow->idsn + 1 + tcp_sk(ssk)->snd_wnd);
+               subflow_set_remote_key(msk, subflow, mp_opt);
+       }
+
+       if (!sock_owned_by_user(sk)) {
+               __mptcp_sync_state(sk, ssk->sk_state);
+       } else {
+               msk->pending_state = ssk->sk_state;
+               __set_bit(MPTCP_SYNC_STATE, &msk->cb_flags);
+       }
+       mptcp_data_unlock(sk);
+}
+
 static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
@@ -499,10 +521,9 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
                if (mp_opt.deny_join_id0)
                        WRITE_ONCE(msk->pm.remote_deny_join_id0, true);
                subflow->mp_capable = 1;
-               subflow_set_remote_key(msk, subflow, &mp_opt);
                MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVEACK);
                mptcp_finish_connect(sk);
-               mptcp_propagate_state(parent, sk);
+               mptcp_propagate_state(parent, sk, subflow, &mp_opt);
        } else if (subflow->request_join) {
                u8 hmac[SHA256_DIGEST_SIZE];
 
@@ -545,8 +566,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
                }
        } else if (mptcp_check_fallback(sk)) {
 fallback:
-               mptcp_rcv_space_init(msk, sk);
-               mptcp_propagate_state(parent, sk);
+               mptcp_propagate_state(parent, sk, subflow, NULL);
        }
        return;
 
@@ -731,17 +751,16 @@ void mptcp_subflow_drop_ctx(struct sock *ssk)
        kfree_rcu(ctx, rcu);
 }
 
-void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
-                                    const struct mptcp_options_received *mp_opt)
+void __mptcp_subflow_fully_established(struct mptcp_sock *msk,
+                                      struct mptcp_subflow_context *subflow,
+                                      const struct mptcp_options_received *mp_opt)
 {
-       struct mptcp_sock *msk = mptcp_sk(subflow->conn);
-
        subflow_set_remote_key(msk, subflow, mp_opt);
        subflow->fully_established = 1;
        WRITE_ONCE(msk->fully_established, true);
 
        if (subflow->is_mptfo)
-               mptcp_fastopen_gen_msk_ackseq(msk, subflow, mp_opt);
+               __mptcp_fastopen_gen_msk_ackseq(msk, subflow, mp_opt);
 }
 
 static struct sock *subflow_syn_recv_sock(const struct sock *sk,
@@ -834,7 +853,6 @@ create_child:
                         * mpc option
                         */
                        if (mp_opt.suboptions & OPTION_MPTCP_MPC_ACK) {
-                               mptcp_subflow_fully_established(ctx, &mp_opt);
                                mptcp_pm_fully_established(owner, child);
                                ctx->pm_notified = 1;
                        }
@@ -1744,10 +1762,9 @@ static void subflow_state_change(struct sock *sk)
        msk = mptcp_sk(parent);
        if (subflow_simultaneous_connect(sk)) {
                mptcp_do_fallback(sk);
-               mptcp_rcv_space_init(msk, sk);
                pr_fallback(msk);
                subflow->conn_finished = 1;
-               mptcp_propagate_state(parent, sk);
+               mptcp_propagate_state(parent, sk, subflow, NULL);
        }
 
        /* as recvmsg() does not acquire the subflow socket for ssk selection
index bcaad9c009fe04dea51bbb30c8270b0953862877..3184cc6be4c9d375fb2bda49d1bbec6623618c77 100644 (file)
@@ -1154,6 +1154,7 @@ static int ip_set_create(struct sk_buff *skb, const struct nfnl_info *info,
        return ret;
 
 cleanup:
+       set->variant->cancel_gc(set);
        set->variant->destroy(set);
 put_out:
        module_put(set->type->me);
@@ -2378,6 +2379,7 @@ ip_set_net_exit(struct net *net)
                set = ip_set(inst, i);
                if (set) {
                        ip_set(inst, i) = NULL;
+                       set->variant->cancel_gc(set);
                        ip_set_destroy_set(set);
                }
        }
index 1136510521a80b9ac8fdb78edd6f8395a6eb3e76..cf3ce72c3de645168b4698176518a02df6a6fa5a 100644 (file)
@@ -432,7 +432,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy)
        u32 i;
 
        for (i = 0; i < jhash_size(t->htable_bits); i++) {
-               n = __ipset_dereference(hbucket(t, i));
+               n = (__force struct hbucket *)hbucket(t, i);
                if (!n)
                        continue;
                if (set->extensions & IPSET_EXT_DESTROY && ext_destroy)
@@ -452,7 +452,7 @@ mtype_destroy(struct ip_set *set)
        struct htype *h = set->data;
        struct list_head *l, *lt;
 
-       mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true);
+       mtype_ahash_destroy(set, (__force struct htable *)h->table, true);
        list_for_each_safe(l, lt, &h->ad) {
                list_del(l);
                kfree(l);
index 0c22a02c2035ccb9c760d71fe2e5dd9c461bf239..3b846cbdc050d324626586fb6ece00985efd874b 100644 (file)
@@ -876,6 +876,7 @@ struct ctnetlink_filter_u32 {
 
 struct ctnetlink_filter {
        u8 family;
+       bool zone_filter;
 
        u_int32_t orig_flags;
        u_int32_t reply_flags;
@@ -992,9 +993,12 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
        if (err)
                goto err_filter;
 
-       err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone);
-       if (err < 0)
-               goto err_filter;
+       if (cda[CTA_ZONE]) {
+               err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone);
+               if (err < 0)
+                       goto err_filter;
+               filter->zone_filter = true;
+       }
 
        if (!cda[CTA_FILTER])
                return filter;
@@ -1148,7 +1152,7 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
        if (filter->family && nf_ct_l3num(ct) != filter->family)
                goto ignore_entry;
 
-       if (filter->zone.id != NF_CT_DEFAULT_ZONE_ID &&
+       if (filter->zone_filter &&
            !nf_ct_zone_equal_any(ct, &filter->zone))
                goto ignore_entry;
 
index c3d7ecbc777ce08525bedee77d637c18682d816c..016c816d91cbc49bfbd5417c295e26667b7be179 100644 (file)
@@ -551,8 +551,11 @@ static void nf_nat_l4proto_unique_tuple(struct nf_conntrack_tuple *tuple,
 find_free_id:
        if (range->flags & NF_NAT_RANGE_PROTO_OFFSET)
                off = (ntohs(*keyptr) - ntohs(range->base_proto.all));
-       else
+       else if ((range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL) ||
+                maniptype != NF_NAT_MANIP_DST)
                off = get_random_u16();
+       else
+               off = 0;
 
        attempts = range_size;
        if (attempts > NF_NAT_MAX_ATTEMPTS)
index fc016befb46ffb2562a10897d8837814e7327377..f8e3f70c35bd558aec8a2b2149a7ff7db0eb3d1f 100644 (file)
@@ -9827,6 +9827,7 @@ dead_elem:
 struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
 {
        struct nft_set_elem_catchall *catchall, *next;
+       u64 tstamp = nft_net_tstamp(gc->net);
        const struct nft_set *set = gc->set;
        struct nft_elem_priv *elem_priv;
        struct nft_set_ext *ext;
@@ -9836,7 +9837,7 @@ struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
        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))
+               if (!__nft_set_elem_expired(ext, tstamp))
                        continue;
 
                gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
@@ -10622,6 +10623,7 @@ static bool nf_tables_valid_genid(struct net *net, u32 genid)
        bool genid_ok;
 
        mutex_lock(&nft_net->commit_mutex);
+       nft_net->tstamp = get_jiffies_64();
 
        genid_ok = genid == 0 || nft_net->base_seq == genid;
        if (!genid_ok)
index 171d1f52d3dd0da711cd63b23ec31d72fa88cdd2..5cf38fc0a366ac55c0ce11798baf7fb93c88283f 100644 (file)
@@ -232,18 +232,25 @@ static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict)
        if (verdict == NF_ACCEPT ||
            verdict == NF_REPEAT ||
            verdict == NF_STOP) {
+               unsigned int ct_verdict = verdict;
+
                rcu_read_lock();
                ct_hook = rcu_dereference(nf_ct_hook);
                if (ct_hook)
-                       verdict = ct_hook->update(entry->state.net, entry->skb);
+                       ct_verdict = ct_hook->update(entry->state.net, entry->skb);
                rcu_read_unlock();
 
-               switch (verdict & NF_VERDICT_MASK) {
+               switch (ct_verdict & NF_VERDICT_MASK) {
+               case NF_ACCEPT:
+                       /* follow userspace verdict, could be REPEAT */
+                       break;
                case NF_STOLEN:
                        nf_queue_entry_free(entry);
                        return;
+               default:
+                       verdict = ct_verdict & NF_VERDICT_MASK;
+                       break;
                }
-
        }
        nf_reinject(entry, verdict);
 }
index f0eeda97bfcd9da2ea98d4ae69c5a1d4a6c30956..1f9474fefe84923e7769efd8ea5c703f5783e37d 100644 (file)
@@ -135,7 +135,7 @@ static void nft_target_eval_bridge(const struct nft_expr *expr,
 
 static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = {
        [NFTA_TARGET_NAME]      = { .type = NLA_NUL_STRING },
-       [NFTA_TARGET_REV]       = { .type = NLA_U32 },
+       [NFTA_TARGET_REV]       = NLA_POLICY_MAX(NLA_BE32, 255),
        [NFTA_TARGET_INFO]      = { .type = NLA_BINARY },
 };
 
@@ -200,6 +200,7 @@ static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1]
 static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
 {
        struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1];
+       u32 l4proto;
        u32 flags;
        int err;
 
@@ -212,12 +213,18 @@ static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
                return -EINVAL;
 
        flags = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_FLAGS]));
-       if (flags & ~NFT_RULE_COMPAT_F_MASK)
+       if (flags & NFT_RULE_COMPAT_F_UNUSED ||
+           flags & ~NFT_RULE_COMPAT_F_MASK)
                return -EINVAL;
        if (flags & NFT_RULE_COMPAT_F_INV)
                *inv = true;
 
-       *proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO]));
+       l4proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO]));
+       if (l4proto > U16_MAX)
+               return -EINVAL;
+
+       *proto = l4proto;
+
        return 0;
 }
 
@@ -419,7 +426,7 @@ static void nft_match_eval(const struct nft_expr *expr,
 
 static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = {
        [NFTA_MATCH_NAME]       = { .type = NLA_NUL_STRING },
-       [NFTA_MATCH_REV]        = { .type = NLA_U32 },
+       [NFTA_MATCH_REV]        = NLA_POLICY_MAX(NLA_BE32, 255),
        [NFTA_MATCH_INFO]       = { .type = NLA_BINARY },
 };
 
@@ -724,7 +731,7 @@ out_put:
 static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = {
        [NFTA_COMPAT_NAME]      = { .type = NLA_NUL_STRING,
                                    .len = NFT_COMPAT_NAME_MAX-1 },
-       [NFTA_COMPAT_REV]       = { .type = NLA_U32 },
+       [NFTA_COMPAT_REV]       = NLA_POLICY_MAX(NLA_BE32, 255),
        [NFTA_COMPAT_TYPE]      = { .type = NLA_U32 },
 };
 
index aac98a3c966e90e76824dfe5dfa362a857128efa..bfd3e5a14dab68484469bdba71af37a460822549 100644 (file)
@@ -476,6 +476,9 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
                break;
 #endif
        case NFT_CT_ID:
+               if (tb[NFTA_CT_DIRECTION])
+                       return -EINVAL;
+
                len = sizeof(u32);
                break;
        default:
index 397351fa4d5f82d8bcec25e1d69f327dc60e0199..ab95760987010b649483bf052fbdba9fde4c9624 100644 (file)
@@ -361,6 +361,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
                ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
        }
 
+       __set_bit(NF_FLOW_HW_BIDIRECTIONAL, &flow->flags);
        ret = flow_offload_add(flowtable, flow);
        if (ret < 0)
                goto err_flow_add;
index 6c2061bfdae6c361c530088ca51aa2790d850ba4..6968a3b342367c6c0cb0df7523fdfd5864038802 100644 (file)
@@ -36,6 +36,7 @@ struct nft_rhash_cmp_arg {
        const struct nft_set            *set;
        const u32                       *key;
        u8                              genmask;
+       u64                             tstamp;
 };
 
 static inline u32 nft_rhash_key(const void *data, u32 len, u32 seed)
@@ -62,7 +63,7 @@ static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg,
                return 1;
        if (nft_set_elem_is_dead(&he->ext))
                return 1;
-       if (nft_set_elem_expired(&he->ext))
+       if (__nft_set_elem_expired(&he->ext, x->tstamp))
                return 1;
        if (!nft_set_elem_active(&he->ext, x->genmask))
                return 1;
@@ -87,6 +88,7 @@ bool nft_rhash_lookup(const struct net *net, const struct nft_set *set,
                .genmask = nft_genmask_cur(net),
                .set     = set,
                .key     = key,
+               .tstamp  = get_jiffies_64(),
        };
 
        he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
@@ -106,6 +108,7 @@ nft_rhash_get(const struct net *net, const struct nft_set *set,
                .genmask = nft_genmask_cur(net),
                .set     = set,
                .key     = elem->key.val.data,
+               .tstamp  = get_jiffies_64(),
        };
 
        he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
@@ -131,6 +134,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key,
                .genmask = NFT_GENMASK_ANY,
                .set     = set,
                .key     = key,
+               .tstamp  = get_jiffies_64(),
        };
 
        he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
@@ -175,6 +179,7 @@ static int nft_rhash_insert(const struct net *net, const struct nft_set *set,
                .genmask = nft_genmask_next(net),
                .set     = set,
                .key     = elem->key.val.data,
+               .tstamp  = nft_net_tstamp(net),
        };
        struct nft_rhash_elem *prev;
 
@@ -216,6 +221,7 @@ nft_rhash_deactivate(const struct net *net, const struct nft_set *set,
                .genmask = nft_genmask_next(net),
                .set     = set,
                .key     = elem->key.val.data,
+               .tstamp  = nft_net_tstamp(net),
        };
 
        rcu_read_lock();
index efd523496be45f59408e8b6dcec7ff40dbcf5844..aa1d9e93a9a04859d48e417501c7f9e889187400 100644 (file)
 #include "nft_set_pipapo_avx2.h"
 #include "nft_set_pipapo.h"
 
-/* Current working bitmap index, toggled between field matches */
-static DEFINE_PER_CPU(bool, nft_pipapo_scratch_index);
-
 /**
  * pipapo_refill() - For each set bit, set bits from selected mapping table item
  * @map:       Bitmap to be scanned for set bits
@@ -412,6 +409,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
                       const u32 *key, const struct nft_set_ext **ext)
 {
        struct nft_pipapo *priv = nft_set_priv(set);
+       struct nft_pipapo_scratch *scratch;
        unsigned long *res_map, *fill_map;
        u8 genmask = nft_genmask_cur(net);
        const u8 *rp = (const u8 *)key;
@@ -422,15 +420,17 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
 
        local_bh_disable();
 
-       map_index = raw_cpu_read(nft_pipapo_scratch_index);
-
        m = rcu_dereference(priv->match);
 
        if (unlikely(!m || !*raw_cpu_ptr(m->scratch)))
                goto out;
 
-       res_map  = *raw_cpu_ptr(m->scratch) + (map_index ? m->bsize_max : 0);
-       fill_map = *raw_cpu_ptr(m->scratch) + (map_index ? 0 : m->bsize_max);
+       scratch = *raw_cpu_ptr(m->scratch);
+
+       map_index = scratch->map_index;
+
+       res_map  = scratch->map + (map_index ? m->bsize_max : 0);
+       fill_map = scratch->map + (map_index ? 0 : m->bsize_max);
 
        memset(res_map, 0xff, m->bsize_max * sizeof(*res_map));
 
@@ -460,7 +460,7 @@ next_match:
                b = pipapo_refill(res_map, f->bsize, f->rules, fill_map, f->mt,
                                  last);
                if (b < 0) {
-                       raw_cpu_write(nft_pipapo_scratch_index, map_index);
+                       scratch->map_index = map_index;
                        local_bh_enable();
 
                        return false;
@@ -477,7 +477,7 @@ next_match:
                         * current inactive bitmap is clean and can be reused as
                         * *next* bitmap (not initial) for the next packet.
                         */
-                       raw_cpu_write(nft_pipapo_scratch_index, map_index);
+                       scratch->map_index = map_index;
                        local_bh_enable();
 
                        return true;
@@ -504,6 +504,7 @@ out:
  * @set:       nftables API set representation
  * @data:      Key data to be matched against existing elements
  * @genmask:   If set, check that element is active in given genmask
+ * @tstamp:    timestamp to check for expired elements
  *
  * This is essentially the same as the lookup function, except that it matches
  * key data against the uncommitted copy and doesn't use preallocated maps for
@@ -513,7 +514,8 @@ out:
  */
 static struct nft_pipapo_elem *pipapo_get(const struct net *net,
                                          const struct nft_set *set,
-                                         const u8 *data, u8 genmask)
+                                         const u8 *data, u8 genmask,
+                                         u64 tstamp)
 {
        struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT);
        struct nft_pipapo *priv = nft_set_priv(set);
@@ -566,7 +568,7 @@ next_match:
                        goto out;
 
                if (last) {
-                       if (nft_set_elem_expired(&f->mt[b].e->ext))
+                       if (__nft_set_elem_expired(&f->mt[b].e->ext, tstamp))
                                goto next_match;
                        if ((genmask &&
                             !nft_set_elem_active(&f->mt[b].e->ext, genmask)))
@@ -603,10 +605,10 @@ static struct nft_elem_priv *
 nft_pipapo_get(const struct net *net, const struct nft_set *set,
               const struct nft_set_elem *elem, unsigned int flags)
 {
-       static struct nft_pipapo_elem *e;
+       struct nft_pipapo_elem *e;
 
        e = pipapo_get(net, set, (const u8 *)elem->key.val.data,
-                      nft_genmask_cur(net));
+                      nft_genmask_cur(net), get_jiffies_64());
        if (IS_ERR(e))
                return ERR_CAST(e);
 
@@ -1108,6 +1110,25 @@ static void pipapo_map(struct nft_pipapo_match *m,
                f->mt[map[i].to + j].e = e;
 }
 
+/**
+ * pipapo_free_scratch() - Free per-CPU map at original (not aligned) address
+ * @m:         Matching data
+ * @cpu:       CPU number
+ */
+static void pipapo_free_scratch(const struct nft_pipapo_match *m, unsigned int cpu)
+{
+       struct nft_pipapo_scratch *s;
+       void *mem;
+
+       s = *per_cpu_ptr(m->scratch, cpu);
+       if (!s)
+               return;
+
+       mem = s;
+       mem -= s->align_off;
+       kfree(mem);
+}
+
 /**
  * pipapo_realloc_scratch() - Reallocate scratch maps for partial match results
  * @clone:     Copy of matching data with pending insertions and deletions
@@ -1121,12 +1142,13 @@ static int pipapo_realloc_scratch(struct nft_pipapo_match *clone,
        int i;
 
        for_each_possible_cpu(i) {
-               unsigned long *scratch;
+               struct nft_pipapo_scratch *scratch;
 #ifdef NFT_PIPAPO_ALIGN
-               unsigned long *scratch_aligned;
+               void *scratch_aligned;
+               u32 align_off;
 #endif
-
-               scratch = kzalloc_node(bsize_max * sizeof(*scratch) * 2 +
+               scratch = kzalloc_node(struct_size(scratch, map,
+                                                  bsize_max * 2) +
                                       NFT_PIPAPO_ALIGN_HEADROOM,
                                       GFP_KERNEL, cpu_to_node(i));
                if (!scratch) {
@@ -1140,14 +1162,25 @@ static int pipapo_realloc_scratch(struct nft_pipapo_match *clone,
                        return -ENOMEM;
                }
 
-               kfree(*per_cpu_ptr(clone->scratch, i));
-
-               *per_cpu_ptr(clone->scratch, i) = scratch;
+               pipapo_free_scratch(clone, i);
 
 #ifdef NFT_PIPAPO_ALIGN
-               scratch_aligned = NFT_PIPAPO_LT_ALIGN(scratch);
-               *per_cpu_ptr(clone->scratch_aligned, i) = scratch_aligned;
+               /* Align &scratch->map (not the struct itself): the extra
+                * %NFT_PIPAPO_ALIGN_HEADROOM bytes passed to kzalloc_node()
+                * above guarantee we can waste up to those bytes in order
+                * to align the map field regardless of its offset within
+                * the struct.
+                */
+               BUILD_BUG_ON(offsetof(struct nft_pipapo_scratch, map) > NFT_PIPAPO_ALIGN_HEADROOM);
+
+               scratch_aligned = NFT_PIPAPO_LT_ALIGN(&scratch->map);
+               scratch_aligned -= offsetof(struct nft_pipapo_scratch, map);
+               align_off = scratch_aligned - (void *)scratch;
+
+               scratch = scratch_aligned;
+               scratch->align_off = align_off;
 #endif
+               *per_cpu_ptr(clone->scratch, i) = scratch;
        }
 
        return 0;
@@ -1173,6 +1206,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
        struct nft_pipapo_match *m = priv->clone;
        u8 genmask = nft_genmask_next(net);
        struct nft_pipapo_elem *e, *dup;
+       u64 tstamp = nft_net_tstamp(net);
        struct nft_pipapo_field *f;
        const u8 *start_p, *end_p;
        int i, bsize_max, err = 0;
@@ -1182,7 +1216,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
        else
                end = start;
 
-       dup = pipapo_get(net, set, start, genmask);
+       dup = pipapo_get(net, set, start, genmask, tstamp);
        if (!IS_ERR(dup)) {
                /* Check if we already have the same exact entry */
                const struct nft_data *dup_key, *dup_end;
@@ -1204,7 +1238,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
 
        if (PTR_ERR(dup) == -ENOENT) {
                /* Look for partially overlapping entries */
-               dup = pipapo_get(net, set, end, nft_genmask_next(net));
+               dup = pipapo_get(net, set, end, nft_genmask_next(net), tstamp);
        }
 
        if (PTR_ERR(dup) != -ENOENT) {
@@ -1301,11 +1335,6 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old)
        if (!new->scratch)
                goto out_scratch;
 
-#ifdef NFT_PIPAPO_ALIGN
-       new->scratch_aligned = alloc_percpu(*new->scratch_aligned);
-       if (!new->scratch_aligned)
-               goto out_scratch;
-#endif
        for_each_possible_cpu(i)
                *per_cpu_ptr(new->scratch, i) = NULL;
 
@@ -1357,10 +1386,7 @@ out_lt:
        }
 out_scratch_realloc:
        for_each_possible_cpu(i)
-               kfree(*per_cpu_ptr(new->scratch, i));
-#ifdef NFT_PIPAPO_ALIGN
-       free_percpu(new->scratch_aligned);
-#endif
+               pipapo_free_scratch(new, i);
 out_scratch:
        free_percpu(new->scratch);
        kfree(new);
@@ -1560,6 +1586,7 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)
 {
        struct nft_pipapo *priv = nft_set_priv(set);
        struct net *net = read_pnet(&set->net);
+       u64 tstamp = nft_net_tstamp(net);
        int rules_f0, first_rule = 0;
        struct nft_pipapo_elem *e;
        struct nft_trans_gc *gc;
@@ -1594,7 +1621,7 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)
                /* synchronous gc never fails, there is no need to set on
                 * NFT_SET_ELEM_DEAD_BIT.
                 */
-               if (nft_set_elem_expired(&e->ext)) {
+               if (__nft_set_elem_expired(&e->ext, tstamp)) {
                        priv->dirty = true;
 
                        gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
@@ -1640,13 +1667,9 @@ static void pipapo_free_match(struct nft_pipapo_match *m)
        int i;
 
        for_each_possible_cpu(i)
-               kfree(*per_cpu_ptr(m->scratch, i));
+               pipapo_free_scratch(m, i);
 
-#ifdef NFT_PIPAPO_ALIGN
-       free_percpu(m->scratch_aligned);
-#endif
        free_percpu(m->scratch);
-
        pipapo_free_fields(m);
 
        kfree(m);
@@ -1769,7 +1792,7 @@ static void *pipapo_deactivate(const struct net *net, const struct nft_set *set,
 {
        struct nft_pipapo_elem *e;
 
-       e = pipapo_get(net, set, data, nft_genmask_next(net));
+       e = pipapo_get(net, set, data, nft_genmask_next(net), nft_net_tstamp(net));
        if (IS_ERR(e))
                return NULL;
 
@@ -2132,7 +2155,7 @@ static int nft_pipapo_init(const struct nft_set *set,
        m->field_count = field_count;
        m->bsize_max = 0;
 
-       m->scratch = alloc_percpu(unsigned long *);
+       m->scratch = alloc_percpu(struct nft_pipapo_scratch *);
        if (!m->scratch) {
                err = -ENOMEM;
                goto out_scratch;
@@ -2140,16 +2163,6 @@ static int nft_pipapo_init(const struct nft_set *set,
        for_each_possible_cpu(i)
                *per_cpu_ptr(m->scratch, i) = NULL;
 
-#ifdef NFT_PIPAPO_ALIGN
-       m->scratch_aligned = alloc_percpu(unsigned long *);
-       if (!m->scratch_aligned) {
-               err = -ENOMEM;
-               goto out_free;
-       }
-       for_each_possible_cpu(i)
-               *per_cpu_ptr(m->scratch_aligned, i) = NULL;
-#endif
-
        rcu_head_init(&m->rcu);
 
        nft_pipapo_for_each_field(f, i, m) {
@@ -2180,9 +2193,6 @@ static int nft_pipapo_init(const struct nft_set *set,
        return 0;
 
 out_free:
-#ifdef NFT_PIPAPO_ALIGN
-       free_percpu(m->scratch_aligned);
-#endif
        free_percpu(m->scratch);
 out_scratch:
        kfree(m);
@@ -2236,11 +2246,8 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx,
 
                nft_set_pipapo_match_destroy(ctx, set, m);
 
-#ifdef NFT_PIPAPO_ALIGN
-               free_percpu(m->scratch_aligned);
-#endif
                for_each_possible_cpu(cpu)
-                       kfree(*per_cpu_ptr(m->scratch, cpu));
+                       pipapo_free_scratch(m, cpu);
                free_percpu(m->scratch);
                pipapo_free_fields(m);
                kfree(m);
@@ -2253,11 +2260,8 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx,
                if (priv->dirty)
                        nft_set_pipapo_match_destroy(ctx, set, m);
 
-#ifdef NFT_PIPAPO_ALIGN
-               free_percpu(priv->clone->scratch_aligned);
-#endif
                for_each_possible_cpu(cpu)
-                       kfree(*per_cpu_ptr(priv->clone->scratch, cpu));
+                       pipapo_free_scratch(priv->clone, cpu);
                free_percpu(priv->clone->scratch);
 
                pipapo_free_fields(priv->clone);
index 1040223da5fa3ab7bbfd4da4d348baee3d22a0d6..3842c7341a9f40a088d78532c4b610f3a99d7d23 100644 (file)
@@ -130,21 +130,29 @@ struct nft_pipapo_field {
        union nft_pipapo_map_bucket *mt;
 };
 
+/**
+ * struct nft_pipapo_scratch - percpu data used for lookup and matching
+ * @map_index: Current working bitmap index, toggled between field matches
+ * @align_off: Offset to get the originally allocated address
+ * @map:       store partial matching results during lookup
+ */
+struct nft_pipapo_scratch {
+       u8 map_index;
+       u32 align_off;
+       unsigned long map[];
+};
+
 /**
  * struct nft_pipapo_match - Data used for lookup and matching
- * @field_count                Amount of fields in set
+ * @field_count:       Amount of fields in set
  * @scratch:           Preallocated per-CPU maps for partial matching results
- * @scratch_aligned:   Version of @scratch aligned to NFT_PIPAPO_ALIGN bytes
  * @bsize_max:         Maximum lookup table bucket size of all fields, in longs
- * @rcu                        Matching data is swapped on commits
+ * @rcu:               Matching data is swapped on commits
  * @f:                 Fields, with lookup and mapping tables
  */
 struct nft_pipapo_match {
        int field_count;
-#ifdef NFT_PIPAPO_ALIGN
-       unsigned long * __percpu *scratch_aligned;
-#endif
-       unsigned long * __percpu *scratch;
+       struct nft_pipapo_scratch * __percpu *scratch;
        size_t bsize_max;
        struct rcu_head rcu;
        struct nft_pipapo_field f[] __counted_by(field_count);
index 52e0d026d30ad2c92f63f589727cdc0b39d7092b..a3a8ddca991894b28aa1a1cd7c84ba0380366b5f 100644 (file)
@@ -57,7 +57,7 @@
 
 /* Jump to label if @reg is zero */
 #define NFT_PIPAPO_AVX2_NOMATCH_GOTO(reg, label)                       \
-       asm_volatile_goto("vptest %%ymm" #reg ", %%ymm" #reg ";"        \
+       asm goto("vptest %%ymm" #reg ", %%ymm" #reg ";" \
                          "je %l[" #label "]" : : : : label)
 
 /* Store 256 bits from YMM register into memory. Contrary to bucket load
@@ -71,9 +71,6 @@
 #define NFT_PIPAPO_AVX2_ZERO(reg)                                      \
        asm volatile("vpxor %ymm" #reg ", %ymm" #reg ", %ymm" #reg)
 
-/* Current working bitmap index, toggled between field matches */
-static DEFINE_PER_CPU(bool, nft_pipapo_avx2_scratch_index);
-
 /**
  * nft_pipapo_avx2_prepare() - Prepare before main algorithm body
  *
@@ -1120,11 +1117,12 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
                            const u32 *key, const struct nft_set_ext **ext)
 {
        struct nft_pipapo *priv = nft_set_priv(set);
-       unsigned long *res, *fill, *scratch;
+       struct nft_pipapo_scratch *scratch;
        u8 genmask = nft_genmask_cur(net);
        const u8 *rp = (const u8 *)key;
        struct nft_pipapo_match *m;
        struct nft_pipapo_field *f;
+       unsigned long *res, *fill;
        bool map_index;
        int i, ret = 0;
 
@@ -1141,15 +1139,16 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
         */
        kernel_fpu_begin_mask(0);
 
-       scratch = *raw_cpu_ptr(m->scratch_aligned);
+       scratch = *raw_cpu_ptr(m->scratch);
        if (unlikely(!scratch)) {
                kernel_fpu_end();
                return false;
        }
-       map_index = raw_cpu_read(nft_pipapo_avx2_scratch_index);
 
-       res  = scratch + (map_index ? m->bsize_max : 0);
-       fill = scratch + (map_index ? 0 : m->bsize_max);
+       map_index = scratch->map_index;
+
+       res  = scratch->map + (map_index ? m->bsize_max : 0);
+       fill = scratch->map + (map_index ? 0 : m->bsize_max);
 
        /* Starting map doesn't need to be set for this implementation */
 
@@ -1221,7 +1220,7 @@ next_match:
 
 out:
        if (i % 2)
-               raw_cpu_write(nft_pipapo_avx2_scratch_index, !map_index);
+               scratch->map_index = !map_index;
        kernel_fpu_end();
 
        return ret >= 0;
index baa3fea4fe65c8f938e665a7fb6b0e4fc0f8f9ad..9944fe479e5361dc140f75be8b90bf3c5deb40f6 100644 (file)
@@ -234,7 +234,7 @@ static void nft_rbtree_gc_elem_remove(struct net *net, struct nft_set *set,
 
 static const struct nft_rbtree_elem *
 nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv,
-                  struct nft_rbtree_elem *rbe, u8 genmask)
+                  struct nft_rbtree_elem *rbe)
 {
        struct nft_set *set = (struct nft_set *)__set;
        struct rb_node *prev = rb_prev(&rbe->node);
@@ -253,7 +253,7 @@ nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv,
        while (prev) {
                rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
                if (nft_rbtree_interval_end(rbe_prev) &&
-                   nft_set_elem_active(&rbe_prev->ext, genmask))
+                   nft_set_elem_active(&rbe_prev->ext, NFT_GENMASK_ANY))
                        break;
 
                prev = rb_prev(prev);
@@ -313,6 +313,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
        struct nft_rbtree *priv = nft_set_priv(set);
        u8 cur_genmask = nft_genmask_cur(net);
        u8 genmask = nft_genmask_next(net);
+       u64 tstamp = nft_net_tstamp(net);
        int d;
 
        /* Descend the tree to search for an existing element greater than the
@@ -360,11 +361,11 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                /* perform garbage collection to avoid bogus overlap reports
                 * but skip new elements in this transaction.
                 */
-               if (nft_set_elem_expired(&rbe->ext) &&
+               if (__nft_set_elem_expired(&rbe->ext, tstamp) &&
                    nft_set_elem_active(&rbe->ext, cur_genmask)) {
                        const struct nft_rbtree_elem *removed_end;
 
-                       removed_end = nft_rbtree_gc_elem(set, priv, rbe, genmask);
+                       removed_end = nft_rbtree_gc_elem(set, priv, rbe);
                        if (IS_ERR(removed_end))
                                return PTR_ERR(removed_end);
 
@@ -551,6 +552,7 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set,
        const struct nft_rbtree *priv = nft_set_priv(set);
        const struct rb_node *parent = priv->root.rb_node;
        u8 genmask = nft_genmask_next(net);
+       u64 tstamp = nft_net_tstamp(net);
        int d;
 
        while (parent != NULL) {
@@ -571,7 +573,7 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set,
                                   nft_rbtree_interval_end(this)) {
                                parent = parent->rb_right;
                                continue;
-                       } else if (nft_set_elem_expired(&rbe->ext)) {
+                       } else if (__nft_set_elem_expired(&rbe->ext, tstamp)) {
                                break;
                        } else if (!nft_set_elem_active(&rbe->ext, genmask)) {
                                parent = parent->rb_left;
@@ -624,9 +626,10 @@ static void nft_rbtree_gc(struct nft_set *set)
 {
        struct nft_rbtree *priv = nft_set_priv(set);
        struct nft_rbtree_elem *rbe, *rbe_end = NULL;
+       struct net *net = read_pnet(&set->net);
+       u64 tstamp = nft_net_tstamp(net);
        struct rb_node *node, *next;
        struct nft_trans_gc *gc;
-       struct net *net;
 
        set  = nft_set_container_of(priv);
        net  = read_pnet(&set->net);
@@ -648,7 +651,7 @@ static void nft_rbtree_gc(struct nft_set *set)
                        rbe_end = rbe;
                        continue;
                }
-               if (!nft_set_elem_expired(&rbe->ext))
+               if (!__nft_set_elem_expired(&rbe->ext, tstamp))
                        continue;
 
                gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
index 88965e2068ac655317169256486613aadf471580..ebc5728aab4eaf0bc165cbdb03e26fc852af9a3e 100644 (file)
@@ -48,6 +48,7 @@ struct ovs_len_tbl {
 
 #define OVS_ATTR_NESTED -1
 #define OVS_ATTR_VARIABLE -2
+#define OVS_COPY_ACTIONS_MAX_DEPTH 16
 
 static bool actions_may_change_flow(const struct nlattr *actions)
 {
@@ -2545,13 +2546,15 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
                                  const struct sw_flow_key *key,
                                  struct sw_flow_actions **sfa,
                                  __be16 eth_type, __be16 vlan_tci,
-                                 u32 mpls_label_count, bool log);
+                                 u32 mpls_label_count, bool log,
+                                 u32 depth);
 
 static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
                                    const struct sw_flow_key *key,
                                    struct sw_flow_actions **sfa,
                                    __be16 eth_type, __be16 vlan_tci,
-                                   u32 mpls_label_count, bool log, bool last)
+                                   u32 mpls_label_count, bool log, bool last,
+                                   u32 depth)
 {
        const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1];
        const struct nlattr *probability, *actions;
@@ -2602,7 +2605,8 @@ static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
                return err;
 
        err = __ovs_nla_copy_actions(net, actions, key, sfa,
-                                    eth_type, vlan_tci, mpls_label_count, log);
+                                    eth_type, vlan_tci, mpls_label_count, log,
+                                    depth + 1);
 
        if (err)
                return err;
@@ -2617,7 +2621,8 @@ static int validate_and_copy_dec_ttl(struct net *net,
                                     const struct sw_flow_key *key,
                                     struct sw_flow_actions **sfa,
                                     __be16 eth_type, __be16 vlan_tci,
-                                    u32 mpls_label_count, bool log)
+                                    u32 mpls_label_count, bool log,
+                                    u32 depth)
 {
        const struct nlattr *attrs[OVS_DEC_TTL_ATTR_MAX + 1];
        int start, action_start, err, rem;
@@ -2660,7 +2665,8 @@ static int validate_and_copy_dec_ttl(struct net *net,
                return action_start;
 
        err = __ovs_nla_copy_actions(net, actions, key, sfa, eth_type,
-                                    vlan_tci, mpls_label_count, log);
+                                    vlan_tci, mpls_label_count, log,
+                                    depth + 1);
        if (err)
                return err;
 
@@ -2674,7 +2680,8 @@ static int validate_and_copy_clone(struct net *net,
                                   const struct sw_flow_key *key,
                                   struct sw_flow_actions **sfa,
                                   __be16 eth_type, __be16 vlan_tci,
-                                  u32 mpls_label_count, bool log, bool last)
+                                  u32 mpls_label_count, bool log, bool last,
+                                  u32 depth)
 {
        int start, err;
        u32 exec;
@@ -2694,7 +2701,8 @@ static int validate_and_copy_clone(struct net *net,
                return err;
 
        err = __ovs_nla_copy_actions(net, attr, key, sfa,
-                                    eth_type, vlan_tci, mpls_label_count, log);
+                                    eth_type, vlan_tci, mpls_label_count, log,
+                                    depth + 1);
        if (err)
                return err;
 
@@ -3063,7 +3071,7 @@ static int validate_and_copy_check_pkt_len(struct net *net,
                                           struct sw_flow_actions **sfa,
                                           __be16 eth_type, __be16 vlan_tci,
                                           u32 mpls_label_count,
-                                          bool log, bool last)
+                                          bool log, bool last, u32 depth)
 {
        const struct nlattr *acts_if_greater, *acts_if_lesser_eq;
        struct nlattr *a[OVS_CHECK_PKT_LEN_ATTR_MAX + 1];
@@ -3111,7 +3119,8 @@ static int validate_and_copy_check_pkt_len(struct net *net,
                return nested_acts_start;
 
        err = __ovs_nla_copy_actions(net, acts_if_lesser_eq, key, sfa,
-                                    eth_type, vlan_tci, mpls_label_count, log);
+                                    eth_type, vlan_tci, mpls_label_count, log,
+                                    depth + 1);
 
        if (err)
                return err;
@@ -3124,7 +3133,8 @@ static int validate_and_copy_check_pkt_len(struct net *net,
                return nested_acts_start;
 
        err = __ovs_nla_copy_actions(net, acts_if_greater, key, sfa,
-                                    eth_type, vlan_tci, mpls_label_count, log);
+                                    eth_type, vlan_tci, mpls_label_count, log,
+                                    depth + 1);
 
        if (err)
                return err;
@@ -3152,12 +3162,16 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
                                  const struct sw_flow_key *key,
                                  struct sw_flow_actions **sfa,
                                  __be16 eth_type, __be16 vlan_tci,
-                                 u32 mpls_label_count, bool log)
+                                 u32 mpls_label_count, bool log,
+                                 u32 depth)
 {
        u8 mac_proto = ovs_key_mac_proto(key);
        const struct nlattr *a;
        int rem, err;
 
+       if (depth > OVS_COPY_ACTIONS_MAX_DEPTH)
+               return -EOVERFLOW;
+
        nla_for_each_nested(a, attr, rem) {
                /* Expected argument lengths, (u32)-1 for variable length. */
                static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = {
@@ -3355,7 +3369,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
                        err = validate_and_copy_sample(net, a, key, sfa,
                                                       eth_type, vlan_tci,
                                                       mpls_label_count,
-                                                      log, last);
+                                                      log, last, depth);
                        if (err)
                                return err;
                        skip_copy = true;
@@ -3426,7 +3440,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
                        err = validate_and_copy_clone(net, a, key, sfa,
                                                      eth_type, vlan_tci,
                                                      mpls_label_count,
-                                                     log, last);
+                                                     log, last, depth);
                        if (err)
                                return err;
                        skip_copy = true;
@@ -3440,7 +3454,8 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
                                                              eth_type,
                                                              vlan_tci,
                                                              mpls_label_count,
-                                                             log, last);
+                                                             log, last,
+                                                             depth);
                        if (err)
                                return err;
                        skip_copy = true;
@@ -3450,7 +3465,8 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
                case OVS_ACTION_ATTR_DEC_TTL:
                        err = validate_and_copy_dec_ttl(net, a, key, sfa,
                                                        eth_type, vlan_tci,
-                                                       mpls_label_count, log);
+                                                       mpls_label_count, log,
+                                                       depth);
                        if (err)
                                return err;
                        skip_copy = true;
@@ -3495,7 +3511,8 @@ int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
 
        (*sfa)->orig_len = nla_len(attr);
        err = __ovs_nla_copy_actions(net, attr, key, sfa, key->eth.type,
-                                    key->eth.vlan.tci, mpls_label_count, log);
+                                    key->eth.vlan.tci, mpls_label_count, log,
+                                    0);
        if (err)
                ovs_nla_free_flow_actions(*sfa);
 
index c71b923764fd7cd7268953b968c5f5749a0b98a6..5627f80013f8b17d3de6284784fe3cbb02bba754 100644 (file)
@@ -425,6 +425,7 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc,
        struct sock *sk = rds_rs_to_sk(rs);
        int ret = 0;
        unsigned long flags;
+       struct rds_incoming *to_drop = NULL;
 
        write_lock_irqsave(&rs->rs_recv_lock, flags);
        if (!list_empty(&inc->i_item)) {
@@ -435,11 +436,14 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc,
                                              -be32_to_cpu(inc->i_hdr.h_len),
                                              inc->i_hdr.h_dport);
                        list_del_init(&inc->i_item);
-                       rds_inc_put(inc);
+                       to_drop = inc;
                }
        }
        write_unlock_irqrestore(&rs->rs_recv_lock, flags);
 
+       if (to_drop)
+               rds_inc_put(to_drop);
+
        rdsdebug("inc %p rs %p still %d dropped %d\n", inc, rs, ret, drop);
        return ret;
 }
@@ -758,16 +762,21 @@ void rds_clear_recv_queue(struct rds_sock *rs)
        struct sock *sk = rds_rs_to_sk(rs);
        struct rds_incoming *inc, *tmp;
        unsigned long flags;
+       LIST_HEAD(to_drop);
 
        write_lock_irqsave(&rs->rs_recv_lock, flags);
        list_for_each_entry_safe(inc, tmp, &rs->rs_recv_queue, i_item) {
                rds_recv_rcvbuf_delta(rs, sk, inc->i_conn->c_lcong,
                                      -be32_to_cpu(inc->i_hdr.h_len),
                                      inc->i_hdr.h_dport);
+               list_move(&inc->i_item, &to_drop);
+       }
+       write_unlock_irqrestore(&rs->rs_recv_lock, flags);
+
+       list_for_each_entry_safe(inc, tmp, &to_drop, i_item) {
                list_del_init(&inc->i_item);
                rds_inc_put(inc);
        }
-       write_unlock_irqrestore(&rs->rs_recv_lock, flags);
 }
 
 /*
index dbeb75c298573adc580568744d6781a5c6193b0d..7818aae1be8e00c1e9b15c918868ca11b40a7213 100644 (file)
@@ -199,11 +199,19 @@ struct rxrpc_host_header {
  */
 struct rxrpc_skb_priv {
        struct rxrpc_connection *conn;  /* Connection referred to (poke packet) */
-       u16             offset;         /* Offset of data */
-       u16             len;            /* Length of data */
-       u8              flags;
+       union {
+               struct {
+                       u16             offset;         /* Offset of data */
+                       u16             len;            /* Length of data */
+                       u8              flags;
 #define RXRPC_RX_VERIFIED      0x01
-
+               };
+               struct {
+                       rxrpc_seq_t     first_ack;      /* First packet in acks table */
+                       u8              nr_acks;        /* Number of acks+nacks */
+                       u8              nr_nacks;       /* Number of nacks */
+               };
+       };
        struct rxrpc_host_header hdr;   /* RxRPC packet header from this packet */
 };
 
@@ -510,7 +518,7 @@ struct rxrpc_connection {
        enum rxrpc_call_completion completion;  /* Completion condition */
        s32                     abort_code;     /* Abort code of connection abort */
        int                     debug_id;       /* debug ID for printks */
-       atomic_t                serial;         /* packet serial number counter */
+       rxrpc_serial_t          tx_serial;      /* Outgoing packet serial number counter */
        unsigned int            hi_serial;      /* highest serial number received */
        u32                     service_id;     /* Service ID, possibly upgraded */
        u32                     security_level; /* Security level selected */
@@ -692,11 +700,11 @@ struct rxrpc_call {
        u8                      cong_dup_acks;  /* Count of ACKs showing missing packets */
        u8                      cong_cumul_acks; /* Cumulative ACK count */
        ktime_t                 cong_tstamp;    /* Last time cwnd was changed */
+       struct sk_buff          *cong_last_nack; /* Last ACK with nacks received */
 
        /* Receive-phase ACK management (ACKs we send). */
        u8                      ackr_reason;    /* reason to ACK */
        u16                     ackr_sack_base; /* Starting slot in SACK table ring */
-       rxrpc_serial_t          ackr_serial;    /* serial of packet being ACK'd */
        rxrpc_seq_t             ackr_window;    /* Base of SACK window */
        rxrpc_seq_t             ackr_wtop;      /* Base of SACK window */
        unsigned int            ackr_nr_unacked; /* Number of unacked packets */
@@ -730,7 +738,8 @@ struct rxrpc_call {
 struct rxrpc_ack_summary {
        u16                     nr_acks;                /* Number of ACKs in packet */
        u16                     nr_new_acks;            /* Number of new ACKs in packet */
-       u16                     nr_rot_new_acks;        /* Number of rotated new ACKs */
+       u16                     nr_new_nacks;           /* Number of new nacks in packet */
+       u16                     nr_retained_nacks;      /* Number of nacks retained between ACKs */
        u8                      ack_reason;
        bool                    saw_nacks;              /* Saw NACKs in packet */
        bool                    new_low_nack;           /* T if new low NACK found */
@@ -822,6 +831,20 @@ static inline bool rxrpc_sending_to_client(const struct rxrpc_txbuf *txb)
 
 #include <trace/events/rxrpc.h>
 
+/*
+ * Allocate the next serial number on a connection.  0 must be skipped.
+ */
+static inline rxrpc_serial_t rxrpc_get_next_serial(struct rxrpc_connection *conn)
+{
+       rxrpc_serial_t serial;
+
+       serial = conn->tx_serial;
+       if (serial == 0)
+               serial = 1;
+       conn->tx_serial = serial + 1;
+       return serial;
+}
+
 /*
  * af_rxrpc.c
  */
index e363f21a20141bb13c931fc0cd40c862c49e5829..0f78544d043be9327ea13cc91fbfa532d6ef4002 100644 (file)
@@ -43,8 +43,6 @@ void rxrpc_propose_delay_ACK(struct rxrpc_call *call, rxrpc_serial_t serial,
        unsigned long expiry = rxrpc_soft_ack_delay;
        unsigned long now = jiffies, ack_at;
 
-       call->ackr_serial = serial;
-
        if (rxrpc_soft_ack_delay < expiry)
                expiry = rxrpc_soft_ack_delay;
        if (call->peer->srtt_us != 0)
@@ -114,6 +112,7 @@ static void rxrpc_congestion_timeout(struct rxrpc_call *call)
 void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb)
 {
        struct rxrpc_ackpacket *ack = NULL;
+       struct rxrpc_skb_priv *sp;
        struct rxrpc_txbuf *txb;
        unsigned long resend_at;
        rxrpc_seq_t transmitted = READ_ONCE(call->tx_transmitted);
@@ -141,14 +140,15 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb)
         * explicitly NAK'd packets.
         */
        if (ack_skb) {
+               sp = rxrpc_skb(ack_skb);
                ack = (void *)ack_skb->data + sizeof(struct rxrpc_wire_header);
 
-               for (i = 0; i < ack->nAcks; i++) {
+               for (i = 0; i < sp->nr_acks; i++) {
                        rxrpc_seq_t seq;
 
                        if (ack->acks[i] & 1)
                                continue;
-                       seq = ntohl(ack->firstPacket) + i;
+                       seq = sp->first_ack + i;
                        if (after(txb->seq, transmitted))
                                break;
                        if (after(txb->seq, seq))
@@ -373,7 +373,6 @@ static void rxrpc_send_initial_ping(struct rxrpc_call *call)
 bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
 {
        unsigned long now, next, t;
-       rxrpc_serial_t ackr_serial;
        bool resend = false, expired = false;
        s32 abort_code;
 
@@ -423,8 +422,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
        if (time_after_eq(now, t)) {
                trace_rxrpc_timer(call, rxrpc_timer_exp_ack, now);
                cmpxchg(&call->delay_ack_at, t, now + MAX_JIFFY_OFFSET);
-               ackr_serial = xchg(&call->ackr_serial, 0);
-               rxrpc_send_ACK(call, RXRPC_ACK_DELAY, ackr_serial,
+               rxrpc_send_ACK(call, RXRPC_ACK_DELAY, 0,
                               rxrpc_propose_ack_ping_for_lost_ack);
        }
 
index 0943e54370ba0e71bcfa6d2238704b0b41c49ee9..9fc9a6c3f685868fe69842d5ac133a1b898674eb 100644 (file)
@@ -686,6 +686,7 @@ static void rxrpc_destroy_call(struct work_struct *work)
 
        del_timer_sync(&call->timer);
 
+       rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack);
        rxrpc_cleanup_ring(call);
        while ((txb = list_first_entry_or_null(&call->tx_sendmsg,
                                               struct rxrpc_txbuf, call_link))) {
index 95f4bc206b3dc9a571abe6fb63cc6fe05575e9c9..1f251d758cb9d8be81856187d78e1994ef179072 100644 (file)
@@ -95,6 +95,14 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
 
        _enter("%d", conn->debug_id);
 
+       if (sp && sp->hdr.type == RXRPC_PACKET_TYPE_ACK) {
+               if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
+                                 &pkt.ack, sizeof(pkt.ack)) < 0)
+                       return;
+               if (pkt.ack.reason == RXRPC_ACK_PING_RESPONSE)
+                       return;
+       }
+
        chan = &conn->channels[channel];
 
        /* If the last call got moved on whilst we were waiting to run, just
@@ -117,7 +125,7 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
        iov[2].iov_base = &ack_info;
        iov[2].iov_len  = sizeof(ack_info);
 
-       serial = atomic_inc_return(&conn->serial);
+       serial = rxrpc_get_next_serial(conn);
 
        pkt.whdr.epoch          = htonl(conn->proto.epoch);
        pkt.whdr.cid            = htonl(conn->proto.cid | channel);
index 92495e73b8699185cf76c60aa88f62d77a29dd56..9691de00ade7522d36174bbe1ab9098c1b52b145 100644 (file)
@@ -45,11 +45,9 @@ static void rxrpc_congestion_management(struct rxrpc_call *call,
        }
 
        cumulative_acks += summary->nr_new_acks;
-       cumulative_acks += summary->nr_rot_new_acks;
        if (cumulative_acks > 255)
                cumulative_acks = 255;
 
-       summary->mode = call->cong_mode;
        summary->cwnd = call->cong_cwnd;
        summary->ssthresh = call->cong_ssthresh;
        summary->cumulative_acks = cumulative_acks;
@@ -151,6 +149,7 @@ out_no_clear_ca:
                cwnd = RXRPC_TX_MAX_WINDOW;
        call->cong_cwnd = cwnd;
        call->cong_cumul_acks = cumulative_acks;
+       summary->mode = call->cong_mode;
        trace_rxrpc_congest(call, summary, acked_serial, change);
        if (resend)
                rxrpc_resend(call, skb);
@@ -213,7 +212,6 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
        list_for_each_entry_rcu(txb, &call->tx_buffer, call_link, false) {
                if (before_eq(txb->seq, call->acks_hard_ack))
                        continue;
-               summary->nr_rot_new_acks++;
                if (test_bit(RXRPC_TXBUF_LAST, &txb->flags)) {
                        set_bit(RXRPC_CALL_TX_LAST, &call->flags);
                        rot_last = true;
@@ -254,6 +252,11 @@ static void rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
 {
        ASSERT(test_bit(RXRPC_CALL_TX_LAST, &call->flags));
 
+       if (unlikely(call->cong_last_nack)) {
+               rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack);
+               call->cong_last_nack = NULL;
+       }
+
        switch (__rxrpc_call_state(call)) {
        case RXRPC_CALL_CLIENT_SEND_REQUEST:
        case RXRPC_CALL_CLIENT_AWAIT_REPLY:
@@ -702,6 +705,43 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
                wake_up(&call->waitq);
 }
 
+/*
+ * Determine how many nacks from the previous ACK have now been satisfied.
+ */
+static rxrpc_seq_t rxrpc_input_check_prev_ack(struct rxrpc_call *call,
+                                             struct rxrpc_ack_summary *summary,
+                                             rxrpc_seq_t seq)
+{
+       struct sk_buff *skb = call->cong_last_nack;
+       struct rxrpc_ackpacket ack;
+       struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+       unsigned int i, new_acks = 0, retained_nacks = 0;
+       rxrpc_seq_t old_seq = sp->first_ack;
+       u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(ack);
+
+       if (after_eq(seq, old_seq + sp->nr_acks)) {
+               summary->nr_new_acks += sp->nr_nacks;
+               summary->nr_new_acks += seq - (old_seq + sp->nr_acks);
+               summary->nr_retained_nacks = 0;
+       } else if (seq == old_seq) {
+               summary->nr_retained_nacks = sp->nr_nacks;
+       } else {
+               for (i = 0; i < sp->nr_acks; i++) {
+                       if (acks[i] == RXRPC_ACK_TYPE_NACK) {
+                               if (before(old_seq + i, seq))
+                                       new_acks++;
+                               else
+                                       retained_nacks++;
+                       }
+               }
+
+               summary->nr_new_acks += new_acks;
+               summary->nr_retained_nacks = retained_nacks;
+       }
+
+       return old_seq + sp->nr_acks;
+}
+
 /*
  * Process individual soft ACKs.
  *
@@ -711,25 +751,51 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
  * the timer on the basis that the peer might just not have processed them at
  * the time the ACK was sent.
  */
-static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
-                                 rxrpc_seq_t seq, int nr_acks,
-                                 struct rxrpc_ack_summary *summary)
+static void rxrpc_input_soft_acks(struct rxrpc_call *call,
+                                 struct rxrpc_ack_summary *summary,
+                                 struct sk_buff *skb,
+                                 rxrpc_seq_t seq,
+                                 rxrpc_seq_t since)
 {
-       unsigned int i;
+       struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+       unsigned int i, old_nacks = 0;
+       rxrpc_seq_t lowest_nak = seq + sp->nr_acks;
+       u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket);
 
-       for (i = 0; i < nr_acks; i++) {
+       for (i = 0; i < sp->nr_acks; i++) {
                if (acks[i] == RXRPC_ACK_TYPE_ACK) {
                        summary->nr_acks++;
-                       summary->nr_new_acks++;
+                       if (after_eq(seq, since))
+                               summary->nr_new_acks++;
                } else {
-                       if (!summary->saw_nacks &&
-                           call->acks_lowest_nak != seq + i) {
-                               call->acks_lowest_nak = seq + i;
-                               summary->new_low_nack = true;
-                       }
                        summary->saw_nacks = true;
+                       if (before(seq, since)) {
+                               /* Overlap with previous ACK */
+                               old_nacks++;
+                       } else {
+                               summary->nr_new_nacks++;
+                               sp->nr_nacks++;
+                       }
+
+                       if (before(seq, lowest_nak))
+                               lowest_nak = seq;
                }
+               seq++;
+       }
+
+       if (lowest_nak != call->acks_lowest_nak) {
+               call->acks_lowest_nak = lowest_nak;
+               summary->new_low_nack = true;
        }
+
+       /* We *can* have more nacks than we did - the peer is permitted to drop
+        * packets it has soft-acked and re-request them.  Further, it is
+        * possible for the nack distribution to change whilst the number of
+        * nacks stays the same or goes down.
+        */
+       if (old_nacks < summary->nr_retained_nacks)
+               summary->nr_new_acks += summary->nr_retained_nacks - old_nacks;
+       summary->nr_retained_nacks = old_nacks;
 }
 
 /*
@@ -773,7 +839,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        struct rxrpc_ackinfo info;
        rxrpc_serial_t ack_serial, acked_serial;
-       rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt;
+       rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt, since;
        int nr_acks, offset, ioffset;
 
        _enter("");
@@ -789,6 +855,8 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
        prev_pkt = ntohl(ack.previousPacket);
        hard_ack = first_soft_ack - 1;
        nr_acks = ack.nAcks;
+       sp->first_ack = first_soft_ack;
+       sp->nr_acks = nr_acks;
        summary.ack_reason = (ack.reason < RXRPC_ACK__INVALID ?
                              ack.reason : RXRPC_ACK__INVALID);
 
@@ -858,6 +926,16 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
        if (nr_acks > 0)
                skb_condense(skb);
 
+       if (call->cong_last_nack) {
+               since = rxrpc_input_check_prev_ack(call, &summary, first_soft_ack);
+               rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack);
+               call->cong_last_nack = NULL;
+       } else {
+               summary.nr_new_acks = first_soft_ack - call->acks_first_seq;
+               call->acks_lowest_nak = first_soft_ack + nr_acks;
+               since = first_soft_ack;
+       }
+
        call->acks_latest_ts = skb->tstamp;
        call->acks_first_seq = first_soft_ack;
        call->acks_prev_seq = prev_pkt;
@@ -866,7 +944,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
        case RXRPC_ACK_PING:
                break;
        default:
-               if (after(acked_serial, call->acks_highest_serial))
+               if (acked_serial && after(acked_serial, call->acks_highest_serial))
                        call->acks_highest_serial = acked_serial;
                break;
        }
@@ -905,8 +983,9 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
        if (nr_acks > 0) {
                if (offset > (int)skb->len - nr_acks)
                        return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_short_sack);
-               rxrpc_input_soft_acks(call, skb->data + offset, first_soft_ack,
-                                     nr_acks, &summary);
+               rxrpc_input_soft_acks(call, &summary, skb, first_soft_ack, since);
+               rxrpc_get_skb(skb, rxrpc_skb_get_last_nack);
+               call->cong_last_nack = skb;
        }
 
        if (test_bit(RXRPC_CALL_TX_LAST, &call->flags) &&
index a0906145e8293ca457fd0b1493ba3892f5f0729a..4a292f860ae37a41bddcd99f7e3bdc6a2c092d29 100644 (file)
@@ -216,7 +216,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
        iov[0].iov_len  = sizeof(txb->wire) + sizeof(txb->ack) + n;
        len = iov[0].iov_len;
 
-       serial = atomic_inc_return(&conn->serial);
+       serial = rxrpc_get_next_serial(conn);
        txb->wire.serial = htonl(serial);
        trace_rxrpc_tx_ack(call->debug_id, serial,
                           ntohl(txb->ack.firstPacket),
@@ -302,7 +302,7 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call)
        iov[0].iov_base = &pkt;
        iov[0].iov_len  = sizeof(pkt);
 
-       serial = atomic_inc_return(&conn->serial);
+       serial = rxrpc_get_next_serial(conn);
        pkt.whdr.serial = htonl(serial);
 
        iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, sizeof(pkt));
@@ -334,7 +334,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
        _enter("%x,{%d}", txb->seq, txb->len);
 
        /* Each transmission of a Tx packet needs a new serial number */
-       serial = atomic_inc_return(&conn->serial);
+       serial = rxrpc_get_next_serial(conn);
        txb->wire.serial = htonl(serial);
 
        if (test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags) &&
@@ -558,7 +558,7 @@ void rxrpc_send_conn_abort(struct rxrpc_connection *conn)
 
        len = iov[0].iov_len + iov[1].iov_len;
 
-       serial = atomic_inc_return(&conn->serial);
+       serial = rxrpc_get_next_serial(conn);
        whdr.serial = htonl(serial);
 
        iov_iter_kvec(&msg.msg_iter, WRITE, iov, 2, len);
index 6c86cbb98d1d601edc9dad728c72f887067a376e..26dc2f26d92d8d67f82229675254d7217c2184e0 100644 (file)
@@ -181,7 +181,7 @@ print:
                   atomic_read(&conn->active),
                   state,
                   key_serial(conn->key),
-                  atomic_read(&conn->serial),
+                  conn->tx_serial,
                   conn->hi_serial,
                   conn->channels[0].call_id,
                   conn->channels[1].call_id,
index b52dedcebce0a7aafe0888f97e79bb81435749f2..6b32d61d4cdc46719d4a011987f6ea112ae59fc1 100644 (file)
@@ -664,7 +664,7 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn)
 
        len = iov[0].iov_len + iov[1].iov_len;
 
-       serial = atomic_inc_return(&conn->serial);
+       serial = rxrpc_get_next_serial(conn);
        whdr.serial = htonl(serial);
 
        ret = kernel_sendmsg(conn->local->socket, &msg, iov, 2, len);
@@ -721,7 +721,7 @@ static int rxkad_send_response(struct rxrpc_connection *conn,
 
        len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
 
-       serial = atomic_inc_return(&conn->serial);
+       serial = rxrpc_get_next_serial(conn);
        whdr.serial = htonl(serial);
 
        rxrpc_local_dont_fragment(conn->local, false);
index 12386f590b0f61f45e4ff40c9ec3605326671a2d..0a1a9e40f237012ecaa561bd563162bbc1802f9b 100644 (file)
@@ -533,8 +533,6 @@ static int mirred_device_event(struct notifier_block *unused,
                                 * net_device are already rcu protected.
                                 */
                                RCU_INIT_POINTER(m->tcfm_dev, NULL);
-                       } else if (m->tcfm_blockid) {
-                               m->tcfm_blockid = 0;
                        }
                        spin_unlock_bh(&m->tcf_lock);
                }
index 5ea84decec19a6b6593e1f9caa31e0e914a52e9d..5337bc46275519a062e54d093df84f3ea8f58583 100644 (file)
@@ -222,6 +222,7 @@ static void __exit exit_em_canid(void)
        tcf_em_unregister(&em_canid_ops);
 }
 
+MODULE_DESCRIPTION("ematch classifier to match CAN IDs embedded in skb CAN frames");
 MODULE_LICENSE("GPL");
 
 module_init(init_em_canid);
index f17b049ea53090d750133422f90b3ad673fd6c41..c90ad7ea26b4697cbedf25a51fc1b92771040c4e 100644 (file)
@@ -87,6 +87,7 @@ static void __exit exit_em_cmp(void)
        tcf_em_unregister(&em_cmp_ops);
 }
 
+MODULE_DESCRIPTION("ematch classifier for basic data types(8/16/32 bit) against skb data");
 MODULE_LICENSE("GPL");
 
 module_init(init_em_cmp);
index 09d8afd04a2a78ac55b0ddd1b424ddcb28b9ba83..8996c73c9779b5fa804e6f913834cf1fe4d071e6 100644 (file)
@@ -1006,6 +1006,7 @@ static void __exit exit_em_meta(void)
        tcf_em_unregister(&em_meta_ops);
 }
 
+MODULE_DESCRIPTION("ematch classifier for various internal kernel metadata, skb metadata and sk metadata");
 MODULE_LICENSE("GPL");
 
 module_init(init_em_meta);
index a83b237cbeb06553c805dfeac3632fd69d6dc3c6..4f9f21a05d5e40aadfdc4c339b8178ad43dc2c8b 100644 (file)
@@ -68,6 +68,7 @@ static void __exit exit_em_nbyte(void)
        tcf_em_unregister(&em_nbyte_ops);
 }
 
+MODULE_DESCRIPTION("ematch classifier for arbitrary skb multi-bytes");
 MODULE_LICENSE("GPL");
 
 module_init(init_em_nbyte);
index f176afb70559eb0a594a2f724765ccb0a1d3b746..420c66203b1777632500ee3d5e2d89a46b50bc4c 100644 (file)
@@ -147,6 +147,7 @@ static void __exit exit_em_text(void)
        tcf_em_unregister(&em_text_ops);
 }
 
+MODULE_DESCRIPTION("ematch classifier for embedded text in skbs");
 MODULE_LICENSE("GPL");
 
 module_init(init_em_text);
index 71b070da043796d1872ae7aecc2348ab6a4b37f1..fdec4db5ec89d047427d62fb6ce95b3649a80f9f 100644 (file)
@@ -52,6 +52,7 @@ static void __exit exit_em_u32(void)
        tcf_em_unregister(&em_u32_ops);
 }
 
+MODULE_DESCRIPTION("ematch skb classifier using 32 bit chunks of data");
 MODULE_LICENSE("GPL");
 
 module_init(init_em_u32);
index 7182c5a450fb5b804d19fdb1b04b75a2c34eb2d0..5c1652181805880ff9f5eaae45e0bab6b00170df 100644 (file)
@@ -38,6 +38,14 @@ void sctp_inq_init(struct sctp_inq *queue)
        INIT_WORK(&queue->immediate, NULL);
 }
 
+/* Properly release the chunk which is being worked on. */
+static inline void sctp_inq_chunk_free(struct sctp_chunk *chunk)
+{
+       if (chunk->head_skb)
+               chunk->skb = chunk->head_skb;
+       sctp_chunk_free(chunk);
+}
+
 /* Release the memory associated with an SCTP inqueue.  */
 void sctp_inq_free(struct sctp_inq *queue)
 {
@@ -53,7 +61,7 @@ void sctp_inq_free(struct sctp_inq *queue)
         * free it as well.
         */
        if (queue->in_progress) {
-               sctp_chunk_free(queue->in_progress);
+               sctp_inq_chunk_free(queue->in_progress);
                queue->in_progress = NULL;
        }
 }
@@ -130,9 +138,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
                                goto new_skb;
                        }
 
-                       if (chunk->head_skb)
-                               chunk->skb = chunk->head_skb;
-                       sctp_chunk_free(chunk);
+                       sctp_inq_chunk_free(chunk);
                        chunk = queue->in_progress = NULL;
                } else {
                        /* Nothing to do. Next chunk in the packet, please. */
index a2cb30af46cb158fcd3a1c12349a0375a1020203..0f53a5c6fd9d9c88c78f51640b179bf214e78bda 100644 (file)
@@ -924,6 +924,7 @@ static int smc_switch_to_fallback(struct smc_sock *smc, int reason_code)
                smc->clcsock->file->private_data = smc->clcsock;
                smc->clcsock->wq.fasync_list =
                        smc->sk.sk_socket->wq.fasync_list;
+               smc->sk.sk_socket->wq.fasync_list = NULL;
 
                /* There might be some wait entries remaining
                 * in smc sk->sk_wq and they should be woken up
index 2cde375477e381aa4a542cd4cf24db067770b466..878415c43527615801186d79a6c0c73b62bf5750 100644 (file)
@@ -1086,6 +1086,12 @@ int tipc_nl_bearer_add(struct sk_buff *skb, struct genl_info *info)
 
 #ifdef CONFIG_TIPC_MEDIA_UDP
        if (attrs[TIPC_NLA_BEARER_UDP_OPTS]) {
+               if (b->media->type_id != TIPC_MEDIA_TYPE_UDP) {
+                       rtnl_unlock();
+                       NL_SET_ERR_MSG(info->extack, "UDP option is unsupported");
+                       return -EINVAL;
+               }
+
                err = tipc_udp_nl_bearer_add(b,
                                             attrs[TIPC_NLA_BEARER_UDP_OPTS]);
                if (err) {
index 31e8a94dfc111b7705fe19b9b4ddee3e6a317a23..9fbc70200cd0f9057b2e34ea3170c001fc4f972c 100644 (file)
@@ -63,6 +63,7 @@ struct tls_decrypt_ctx {
        u8 iv[TLS_MAX_IV_SIZE];
        u8 aad[TLS_MAX_AAD_SIZE];
        u8 tail;
+       bool free_sgout;
        struct scatterlist sg[];
 };
 
@@ -187,7 +188,6 @@ static void tls_decrypt_done(void *data, int err)
        struct aead_request *aead_req = data;
        struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
        struct scatterlist *sgout = aead_req->dst;
-       struct scatterlist *sgin = aead_req->src;
        struct tls_sw_context_rx *ctx;
        struct tls_decrypt_ctx *dctx;
        struct tls_context *tls_ctx;
@@ -196,6 +196,17 @@ static void tls_decrypt_done(void *data, int err)
        struct sock *sk;
        int aead_size;
 
+       /* If requests get too backlogged crypto API returns -EBUSY and calls
+        * ->complete(-EINPROGRESS) immediately followed by ->complete(0)
+        * to make waiting for backlog to flush with crypto_wait_req() easier.
+        * First wait converts -EBUSY -> -EINPROGRESS, and the second one
+        * -EINPROGRESS -> 0.
+        * We have a single struct crypto_async_request per direction, this
+        * scheme doesn't help us, so just ignore the first ->complete().
+        */
+       if (err == -EINPROGRESS)
+               return;
+
        aead_size = sizeof(*aead_req) + crypto_aead_reqsize(aead);
        aead_size = ALIGN(aead_size, __alignof__(*dctx));
        dctx = (void *)((u8 *)aead_req + aead_size);
@@ -213,7 +224,7 @@ static void tls_decrypt_done(void *data, int err)
        }
 
        /* Free the destination pages if skb was not decrypted inplace */
-       if (sgout != sgin) {
+       if (dctx->free_sgout) {
                /* Skip the first S/G entry as it points to AAD */
                for_each_sg(sg_next(sgout), sg, UINT_MAX, pages) {
                        if (!sg)
@@ -224,10 +235,17 @@ static void tls_decrypt_done(void *data, int err)
 
        kfree(aead_req);
 
-       spin_lock_bh(&ctx->decrypt_compl_lock);
-       if (!atomic_dec_return(&ctx->decrypt_pending))
+       if (atomic_dec_and_test(&ctx->decrypt_pending))
                complete(&ctx->async_wait.completion);
-       spin_unlock_bh(&ctx->decrypt_compl_lock);
+}
+
+static int tls_decrypt_async_wait(struct tls_sw_context_rx *ctx)
+{
+       if (!atomic_dec_and_test(&ctx->decrypt_pending))
+               crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
+       atomic_inc(&ctx->decrypt_pending);
+
+       return ctx->async_wait.err;
 }
 
 static int tls_do_decryption(struct sock *sk,
@@ -253,6 +271,7 @@ static int tls_do_decryption(struct sock *sk,
                aead_request_set_callback(aead_req,
                                          CRYPTO_TFM_REQ_MAY_BACKLOG,
                                          tls_decrypt_done, aead_req);
+               DEBUG_NET_WARN_ON_ONCE(atomic_read(&ctx->decrypt_pending) < 1);
                atomic_inc(&ctx->decrypt_pending);
        } else {
                aead_request_set_callback(aead_req,
@@ -261,6 +280,10 @@ static int tls_do_decryption(struct sock *sk,
        }
 
        ret = crypto_aead_decrypt(aead_req);
+       if (ret == -EBUSY) {
+               ret = tls_decrypt_async_wait(ctx);
+               ret = ret ?: -EINPROGRESS;
+       }
        if (ret == -EINPROGRESS) {
                if (darg->async)
                        return 0;
@@ -439,9 +462,10 @@ static void tls_encrypt_done(void *data, int err)
        struct tls_rec *rec = data;
        struct scatterlist *sge;
        struct sk_msg *msg_en;
-       bool ready = false;
        struct sock *sk;
-       int pending;
+
+       if (err == -EINPROGRESS) /* see the comment in tls_decrypt_done() */
+               return;
 
        msg_en = &rec->msg_encrypted;
 
@@ -476,23 +500,25 @@ static void tls_encrypt_done(void *data, int err)
                /* If received record is at head of tx_list, schedule tx */
                first_rec = list_first_entry(&ctx->tx_list,
                                             struct tls_rec, list);
-               if (rec == first_rec)
-                       ready = true;
+               if (rec == first_rec) {
+                       /* Schedule the transmission */
+                       if (!test_and_set_bit(BIT_TX_SCHEDULED,
+                                             &ctx->tx_bitmask))
+                               schedule_delayed_work(&ctx->tx_work.work, 1);
+               }
        }
 
-       spin_lock_bh(&ctx->encrypt_compl_lock);
-       pending = atomic_dec_return(&ctx->encrypt_pending);
-
-       if (!pending && ctx->async_notify)
+       if (atomic_dec_and_test(&ctx->encrypt_pending))
                complete(&ctx->async_wait.completion);
-       spin_unlock_bh(&ctx->encrypt_compl_lock);
+}
 
-       if (!ready)
-               return;
+static int tls_encrypt_async_wait(struct tls_sw_context_tx *ctx)
+{
+       if (!atomic_dec_and_test(&ctx->encrypt_pending))
+               crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
+       atomic_inc(&ctx->encrypt_pending);
 
-       /* Schedule the transmission */
-       if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
-               schedule_delayed_work(&ctx->tx_work.work, 1);
+       return ctx->async_wait.err;
 }
 
 static int tls_do_encryption(struct sock *sk,
@@ -541,9 +567,14 @@ static int tls_do_encryption(struct sock *sk,
 
        /* Add the record in tx_list */
        list_add_tail((struct list_head *)&rec->list, &ctx->tx_list);
+       DEBUG_NET_WARN_ON_ONCE(atomic_read(&ctx->encrypt_pending) < 1);
        atomic_inc(&ctx->encrypt_pending);
 
        rc = crypto_aead_encrypt(aead_req);
+       if (rc == -EBUSY) {
+               rc = tls_encrypt_async_wait(ctx);
+               rc = rc ?: -EINPROGRESS;
+       }
        if (!rc || rc != -EINPROGRESS) {
                atomic_dec(&ctx->encrypt_pending);
                sge->offset -= prot->prepend_size;
@@ -984,7 +1015,6 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg,
        int num_zc = 0;
        int orig_size;
        int ret = 0;
-       int pending;
 
        if (!eor && (msg->msg_flags & MSG_EOR))
                return -EINVAL;
@@ -1163,24 +1193,12 @@ trim_sgl:
        if (!num_async) {
                goto send_end;
        } else if (num_zc) {
-               /* Wait for pending encryptions to get completed */
-               spin_lock_bh(&ctx->encrypt_compl_lock);
-               ctx->async_notify = true;
-
-               pending = atomic_read(&ctx->encrypt_pending);
-               spin_unlock_bh(&ctx->encrypt_compl_lock);
-               if (pending)
-                       crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
-               else
-                       reinit_completion(&ctx->async_wait.completion);
-
-               /* There can be no concurrent accesses, since we have no
-                * pending encrypt operations
-                */
-               WRITE_ONCE(ctx->async_notify, false);
+               int err;
 
-               if (ctx->async_wait.err) {
-                       ret = ctx->async_wait.err;
+               /* Wait for pending encryptions to get completed */
+               err = tls_encrypt_async_wait(ctx);
+               if (err) {
+                       ret = err;
                        copied = 0;
                }
        }
@@ -1229,7 +1247,6 @@ void tls_sw_splice_eof(struct socket *sock)
        ssize_t copied = 0;
        bool retrying = false;
        int ret = 0;
-       int pending;
 
        if (!ctx->open_rec)
                return;
@@ -1264,22 +1281,7 @@ retry:
        }
 
        /* Wait for pending encryptions to get completed */
-       spin_lock_bh(&ctx->encrypt_compl_lock);
-       ctx->async_notify = true;
-
-       pending = atomic_read(&ctx->encrypt_pending);
-       spin_unlock_bh(&ctx->encrypt_compl_lock);
-       if (pending)
-               crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
-       else
-               reinit_completion(&ctx->async_wait.completion);
-
-       /* There can be no concurrent accesses, since we have no pending
-        * encrypt operations
-        */
-       WRITE_ONCE(ctx->async_notify, false);
-
-       if (ctx->async_wait.err)
+       if (tls_encrypt_async_wait(ctx))
                goto unlock;
 
        /* Transmit if any encryptions have completed */
@@ -1581,6 +1583,7 @@ static int tls_decrypt_sg(struct sock *sk, struct iov_iter *out_iov,
        } else if (out_sg) {
                memcpy(sgout, out_sg, n_sgout * sizeof(*sgout));
        }
+       dctx->free_sgout = !!pages;
 
        /* Prepare and submit AEAD request */
        err = tls_do_decryption(sk, sgin, sgout, dctx->iv,
@@ -2109,16 +2112,10 @@ put_on_rx_list:
 
 recv_end:
        if (async) {
-               int ret, pending;
+               int ret;
 
                /* Wait for all previously submitted records to be decrypted */
-               spin_lock_bh(&ctx->decrypt_compl_lock);
-               reinit_completion(&ctx->async_wait.completion);
-               pending = atomic_read(&ctx->decrypt_pending);
-               spin_unlock_bh(&ctx->decrypt_compl_lock);
-               ret = 0;
-               if (pending)
-                       ret = crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
+               ret = tls_decrypt_async_wait(ctx);
                __skb_queue_purge(&ctx->async_hold);
 
                if (ret) {
@@ -2135,7 +2132,6 @@ recv_end:
                else
                        err = process_rx_list(ctx, msg, &control, 0,
                                              async_copy_bytes, is_peek);
-               decrypted += max(err, 0);
        }
 
        copied += decrypted;
@@ -2435,16 +2431,9 @@ void tls_sw_release_resources_tx(struct sock *sk)
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
        struct tls_rec *rec, *tmp;
-       int pending;
 
        /* Wait for any pending async encryptions to complete */
-       spin_lock_bh(&ctx->encrypt_compl_lock);
-       ctx->async_notify = true;
-       pending = atomic_read(&ctx->encrypt_pending);
-       spin_unlock_bh(&ctx->encrypt_compl_lock);
-
-       if (pending)
-               crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
+       tls_encrypt_async_wait(ctx);
 
        tls_tx_records(sk, -1);
 
@@ -2607,7 +2596,7 @@ static struct tls_sw_context_tx *init_ctx_tx(struct tls_context *ctx, struct soc
        }
 
        crypto_init_wait(&sw_ctx_tx->async_wait);
-       spin_lock_init(&sw_ctx_tx->encrypt_compl_lock);
+       atomic_set(&sw_ctx_tx->encrypt_pending, 1);
        INIT_LIST_HEAD(&sw_ctx_tx->tx_list);
        INIT_DELAYED_WORK(&sw_ctx_tx->tx_work.work, tx_work_handler);
        sw_ctx_tx->tx_work.sk = sk;
@@ -2628,7 +2617,7 @@ static struct tls_sw_context_rx *init_ctx_rx(struct tls_context *ctx)
        }
 
        crypto_init_wait(&sw_ctx_rx->async_wait);
-       spin_lock_init(&sw_ctx_rx->decrypt_compl_lock);
+       atomic_set(&sw_ctx_rx->decrypt_pending, 1);
        init_waitqueue_head(&sw_ctx_rx->wq);
        skb_queue_head_init(&sw_ctx_rx->rx_list);
        skb_queue_head_init(&sw_ctx_rx->async_hold);
index 2405f0f9af31c0ccefe2aa404002cfab8583c090..2ff7ddbaa782e341e1614a4d5bd295c87664e7dd 100644 (file)
@@ -314,6 +314,18 @@ void unix_gc(void)
        /* Here we are. Hitlist is filled. Die. */
        __skb_queue_purge(&hitlist);
 
+#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
+       while (!list_empty(&gc_candidates)) {
+               u = list_entry(gc_candidates.next, struct unix_sock, link);
+               if (u->oob_skb) {
+                       struct sk_buff *skb = u->oob_skb;
+
+                       u->oob_skb = NULL;
+                       kfree_skb(skb);
+               }
+       }
+#endif
+
        spin_lock(&unix_gc_lock);
 
        /* There could be io_uring registered files, just push them back to
index 409d74c57ca0d8c8d36c2260897fce39557620ee..3fb1b637352a9d0b469206d890601031ffd4c68f 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2010         Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2023 Intel Corporation
+ * Copyright (C) 2018-2024 Intel Corporation
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -1661,6 +1661,7 @@ void wiphy_delayed_work_queue(struct wiphy *wiphy,
                              unsigned long delay)
 {
        if (!delay) {
+               del_timer(&dwork->timer);
                wiphy_work_queue(wiphy, &dwork->work);
                return;
        }
index 2249b1a89d1c4cee36bda840d64dda612d367c5f..389a52c29bfc728c2437037b4f0e180b974d12ba 100644 (file)
@@ -1731,6 +1731,61 @@ static void cfg80211_update_hidden_bsses(struct cfg80211_internal_bss *known,
        }
 }
 
+static void cfg80211_check_stuck_ecsa(struct cfg80211_registered_device *rdev,
+                                     struct cfg80211_internal_bss *known,
+                                     const struct cfg80211_bss_ies *old)
+{
+       const struct ieee80211_ext_chansw_ie *ecsa;
+       const struct element *elem_new, *elem_old;
+       const struct cfg80211_bss_ies *new, *bcn;
+
+       if (known->pub.proberesp_ecsa_stuck)
+               return;
+
+       new = rcu_dereference_protected(known->pub.proberesp_ies,
+                                       lockdep_is_held(&rdev->bss_lock));
+       if (WARN_ON(!new))
+               return;
+
+       if (new->tsf - old->tsf < USEC_PER_SEC)
+               return;
+
+       elem_old = cfg80211_find_elem(WLAN_EID_EXT_CHANSWITCH_ANN,
+                                     old->data, old->len);
+       if (!elem_old)
+               return;
+
+       elem_new = cfg80211_find_elem(WLAN_EID_EXT_CHANSWITCH_ANN,
+                                     new->data, new->len);
+       if (!elem_new)
+               return;
+
+       bcn = rcu_dereference_protected(known->pub.beacon_ies,
+                                       lockdep_is_held(&rdev->bss_lock));
+       if (bcn &&
+           cfg80211_find_elem(WLAN_EID_EXT_CHANSWITCH_ANN,
+                              bcn->data, bcn->len))
+               return;
+
+       if (elem_new->datalen != elem_old->datalen)
+               return;
+       if (elem_new->datalen < sizeof(struct ieee80211_ext_chansw_ie))
+               return;
+       if (memcmp(elem_new->data, elem_old->data, elem_new->datalen))
+               return;
+
+       ecsa = (void *)elem_new->data;
+
+       if (!ecsa->mode)
+               return;
+
+       if (ecsa->new_ch_num !=
+           ieee80211_frequency_to_channel(known->pub.channel->center_freq))
+               return;
+
+       known->pub.proberesp_ecsa_stuck = 1;
+}
+
 static bool
 cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
                          struct cfg80211_internal_bss *known,
@@ -1750,8 +1805,10 @@ cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
                /* Override possible earlier Beacon frame IEs */
                rcu_assign_pointer(known->pub.ies,
                                   new->pub.proberesp_ies);
-               if (old)
+               if (old) {
+                       cfg80211_check_stuck_ecsa(rdev, known, old);
                        kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
+               }
        }
 
        if (rcu_access_pointer(new->pub.beacon_ies)) {
index 41533c631431493882a7fa427d393c4b6a753e74..e6da7e8495c9cfdc3e81eb408e444a39442a2c9b 100644 (file)
@@ -858,4 +858,5 @@ int xfrm_count_pfkey_enc_supported(void)
 }
 EXPORT_SYMBOL_GPL(xfrm_count_pfkey_enc_supported);
 
+MODULE_DESCRIPTION("XFRM Algorithm interface");
 MODULE_LICENSE("GPL");
index ad01997c3aa9dd851a3fa4ad6dd6c877eaaddd36..f037be190baeacf8a7fc4c26240dd224a39cb984 100644 (file)
@@ -3888,5 +3888,6 @@ static void __exit xfrm_user_exit(void)
 
 module_init(xfrm_user_init);
 module_exit(xfrm_user_exit);
+MODULE_DESCRIPTION("XFRM User interface");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
index 7048bb3594d65be6d132d4103ee801fadf087b7e..634e81d83efd9577337e37f1ce42911574b0adf9 100644 (file)
@@ -4,14 +4,14 @@
 #define __ASM_GOTO_WORKAROUND_H
 
 /*
- * This will bring in asm_volatile_goto and asm_inline macro definitions
+ * This will bring in asm_goto_output and asm_inline macro definitions
  * if enabled by compiler and config options.
  */
 #include <linux/types.h>
 
-#ifdef asm_volatile_goto
-#undef asm_volatile_goto
-#define asm_volatile_goto(x...) asm volatile("invalid use of asm_volatile_goto")
+#ifdef asm_goto_output
+#undef asm_goto_output
+#define asm_goto_output(x...) asm volatile("invalid use of asm_goto_output")
 #endif
 
 /*
index 3aaad75c9ce8531b6f214ad8bd469d1c571908c7..7035ee35a393020303304741092e6b016e02669c 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/backing-dev.h>
 #include <linux/string.h>
 #include <linux/msg.h>
+#include <linux/overflow.h>
 #include <net/flow.h>
 
 /* How many LSMs were built into the kernel? */
@@ -4015,6 +4016,7 @@ int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
        struct security_hook_list *hp;
        struct lsm_ctx *lctx;
        int rc = LSM_RET_DEFAULT(setselfattr);
+       u64 required_len;
 
        if (flags)
                return -EINVAL;
@@ -4027,8 +4029,9 @@ int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
        if (IS_ERR(lctx))
                return PTR_ERR(lctx);
 
-       if (size < lctx->len || size < lctx->ctx_len + sizeof(*lctx) ||
-           lctx->len < lctx->ctx_len + sizeof(*lctx)) {
+       if (size < lctx->len ||
+           check_add_overflow(sizeof(*lctx), lctx->ctx_len, &required_len) ||
+           lctx->len < required_len) {
                rc = -EINVAL;
                goto free_out;
        }
index 21a90b3c4cc7300e0abfc301e34338170dd6b911..8e0ff70fb6101ff9b94aab0d79c4b6f7cf90498d 100644 (file)
@@ -156,7 +156,7 @@ config SND_HDA_SCODEC_CS35L56_I2C
        depends on I2C
        depends on ACPI || COMPILE_TEST
        depends on SND_SOC
-       select CS_DSP
+       select FW_CS_DSP
        select SND_HDA_GENERIC
        select SND_SOC_CS35L56_SHARED
        select SND_HDA_SCODEC_CS35L56
@@ -171,7 +171,7 @@ config SND_HDA_SCODEC_CS35L56_SPI
        depends on SPI_MASTER
        depends on ACPI || COMPILE_TEST
        depends on SND_SOC
-       select CS_DSP
+       select FW_CS_DSP
        select SND_HDA_GENERIC
        select SND_SOC_CS35L56_SHARED
        select SND_HDA_SCODEC_CS35L56
index d74cf11eef1ea6fcb1bae71b9c00aad87203de40..87dcb367e2391939de02f24c6edd1dd8a4aac8a8 100644 (file)
@@ -91,10 +91,12 @@ static const struct cs35l41_config cs35l41_config_table[] = {
        { "10431D1F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
        { "10431DA2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
        { "10431E02", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
+       { "10431E12", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
        { "10431EE2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
        { "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
        { "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
        { "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
+       { "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
        { "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
        { "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
        { "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
@@ -427,10 +429,12 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
        { "CSC3551", "10431D1F", generic_dsd_config },
        { "CSC3551", "10431DA2", generic_dsd_config },
        { "CSC3551", "10431E02", generic_dsd_config },
+       { "CSC3551", "10431E12", generic_dsd_config },
        { "CSC3551", "10431EE2", generic_dsd_config },
        { "CSC3551", "10431F12", generic_dsd_config },
        { "CSC3551", "10431F1F", generic_dsd_config },
        { "CSC3551", "10431F62", generic_dsd_config },
+       { "CSC3551", "17AA386F", generic_dsd_config },
        { "CSC3551", "17AA38B4", generic_dsd_config },
        { "CSC3551", "17AA38B5", generic_dsd_config },
        { "CSC3551", "17AA38B6", generic_dsd_config },
index e8819e8a98763cb5a4760768be387a4a387c384d..e8209178d87bbcc88551e6773c90c9fec7d98af2 100644 (file)
@@ -344,6 +344,7 @@ enum {
        CXT_FIXUP_HP_ZBOOK_MUTE_LED,
        CXT_FIXUP_HEADSET_MIC,
        CXT_FIXUP_HP_MIC_NO_PRESENCE,
+       CXT_PINCFG_SWS_JS201D,
 };
 
 /* for hda_fixup_thinkpad_acpi() */
@@ -841,6 +842,17 @@ static const struct hda_pintbl cxt_pincfg_lemote[] = {
        {}
 };
 
+/* SuoWoSi/South-holding JS201D with sn6140 */
+static const struct hda_pintbl cxt_pincfg_sws_js201d[] = {
+       { 0x16, 0x03211040 }, /* hp out */
+       { 0x17, 0x91170110 }, /* SPK/Class_D */
+       { 0x18, 0x95a70130 }, /* Internal mic */
+       { 0x19, 0x03a11020 }, /* Headset Mic */
+       { 0x1a, 0x40f001f0 }, /* Not used */
+       { 0x21, 0x40f001f0 }, /* Not used */
+       {}
+};
+
 static const struct hda_fixup cxt_fixups[] = {
        [CXT_PINCFG_LENOVO_X200] = {
                .type = HDA_FIXUP_PINS,
@@ -996,6 +1008,10 @@ static const struct hda_fixup cxt_fixups[] = {
                .chained = true,
                .chain_id = CXT_FIXUP_HEADSET_MIC,
        },
+       [CXT_PINCFG_SWS_JS201D] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = cxt_pincfg_sws_js201d,
+       },
 };
 
 static const struct snd_pci_quirk cxt5045_fixups[] = {
@@ -1069,6 +1085,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x8458, "HP Z2 G4 mini premium", CXT_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
+       SND_PCI_QUIRK(0x14f1, 0x0265, "SWS JS201D", CXT_PINCFG_SWS_JS201D),
        SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
@@ -1109,6 +1126,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
        { .id = CXT_FIXUP_HP_ZBOOK_MUTE_LED, .name = "hp-zbook-mute-led" },
        { .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" },
        { .id = CXT_PINCFG_LENOVO_NOTEBOOK, .name = "lenovo-20149" },
+       { .id = CXT_PINCFG_SWS_JS201D, .name = "sws-js201d" },
        {}
 };
 
index 6994c4c5073cbb6fd5ad932186db35970c7cbd0f..0ec1312bffd5b797d09dbbb96ef9ab9e8a244c4b 100644 (file)
@@ -9737,7 +9737,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
        SND_PCI_QUIRK(0x1028, 0x0beb, "Dell XPS 15 9530 (2023)", ALC289_FIXUP_DELL_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0c0b, "Dell Oasis 14 RPL-P", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
        SND_PCI_QUIRK(0x1028, 0x0c0d, "Dell Oasis", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
+       SND_PCI_QUIRK(0x1028, 0x0c0e, "Dell Oasis 16", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
        SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
        SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
        SND_PCI_QUIRK(0x1028, 0x0c1b, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
@@ -9928,6 +9930,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8b0f, "HP Elite mt645 G7 Mobile Thin Client U81", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b2f, "HP 255 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
        SND_PCI_QUIRK(0x103c, 0x8b42, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b43, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
@@ -9935,6 +9938,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8b45, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b46, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b47, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8b59, "HP Elite mt645 G7 Mobile Thin Client U89", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b63, "HP Elite Dragonfly 13.5 inch G4", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
@@ -10003,6 +10007,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
        SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZI/ZJ/ZQ/ZU/ZV", ALC285_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x16d3, "ASUS UX5304VA", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
@@ -10046,14 +10051,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2),
-       SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2),
-       SND_PCI_QUIRK(0x1043, 0x1f62, "ASUS UX7602ZM", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
-       SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
        SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS),
        SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
-       SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1f12, "ASUS UM5302", ALC287_FIXUP_CS35L41_I2C_2),
@@ -10260,6 +10263,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
        SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
        SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+       SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
        SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C),
        SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C),
index 2dd809de62e5a4ac049a49752f447b0a8b4a3be6..1bfb00102a77a4d49695efeaf7016eded961345b 100644 (file)
@@ -710,7 +710,7 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
 
        strscpy(comps->name, dev_name(dev), sizeof(comps->name));
 
-       ret = tascodec_init(tas_hda->priv, codec, tasdev_fw_ready);
+       ret = tascodec_init(tas_hda->priv, codec, THIS_MODULE, tasdev_fw_ready);
        if (!ret)
                comps->playback_hook = tas2781_hda_playback_hook;
 
index 23d44a50d8157212aa5bbaa49ecd1e9acbe9aa00..cc231185d72c3dbfdb32f306cbbe6508e9a06e15 100644 (file)
@@ -234,6 +234,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "82UG"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "82UU"),
+               }
+       },
        {
                .driver_data = &acp6x_card,
                .matches = {
@@ -248,6 +255,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "82YM"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "83AS"),
+               }
+       },
        {
                .driver_data = &acp6x_card,
                .matches = {
index 02fba4bc0a14f4cc44690ffed69bd5217409b6e9..995d979b6d87e7e889a4cf326e1477399f742650 100644 (file)
@@ -51,7 +51,6 @@ static const struct reg_default cs35l56_reg_defaults[] = {
        { CS35L56_SWIRE_DP3_CH2_INPUT,          0x00000019 },
        { CS35L56_SWIRE_DP3_CH3_INPUT,          0x00000029 },
        { CS35L56_SWIRE_DP3_CH4_INPUT,          0x00000028 },
-       { CS35L56_IRQ1_CFG,                     0x00000000 },
        { CS35L56_IRQ1_MASK_1,                  0x83ffffff },
        { CS35L56_IRQ1_MASK_2,                  0xffff7fff },
        { CS35L56_IRQ1_MASK_4,                  0xe0ffffff },
index c23e29da4cfb9f43fa52611fdeea96adad4a0b30..2c1313e34cce4969ca393ef774e305a4d18198b5 100644 (file)
@@ -5,6 +5,7 @@
 // Copyright (C) 2023 Cirrus Logic, Inc. and
 //                    Cirrus Logic International Semiconductor Ltd.
 
+#include <linux/acpi.h>
 #include <linux/completion.h>
 #include <linux/debugfs.h>
 #include <linux/delay.h>
@@ -15,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -68,63 +70,7 @@ static const char * const cs35l56_asp1_mux_control_names[] = {
        "ASP1 TX1 Source", "ASP1 TX2 Source", "ASP1 TX3 Source", "ASP1 TX4 Source"
 };
 
-static int cs35l56_dspwait_asp1tx_get(struct snd_kcontrol *kcontrol,
-                                     struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
-       struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
-       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       int index = e->shift_l;
-       unsigned int addr, val;
-       int ret;
-
-       /* Wait for mux to be initialized */
-       cs35l56_wait_dsp_ready(cs35l56);
-       flush_work(&cs35l56->mux_init_work);
-
-       addr = cs35l56_asp1_mixer_regs[index];
-       ret = regmap_read(cs35l56->base.regmap, addr, &val);
-       if (ret)
-               return ret;
-
-       val &= CS35L56_ASP_TXn_SRC_MASK;
-       ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);
-
-       return 0;
-}
-
-static int cs35l56_dspwait_asp1tx_put(struct snd_kcontrol *kcontrol,
-                                     struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
-       struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
-       struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
-       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       int item = ucontrol->value.enumerated.item[0];
-       int index = e->shift_l;
-       unsigned int addr, val;
-       bool changed;
-       int ret;
-
-       /* Wait for mux to be initialized */
-       cs35l56_wait_dsp_ready(cs35l56);
-       flush_work(&cs35l56->mux_init_work);
-
-       addr = cs35l56_asp1_mixer_regs[index];
-       val = snd_soc_enum_item_to_val(e, item);
-
-       ret = regmap_update_bits_check(cs35l56->base.regmap, addr,
-                                      CS35L56_ASP_TXn_SRC_MASK, val, &changed);
-       if (!ret)
-               return ret;
-
-       if (changed)
-               snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL);
-
-       return changed;
-}
-
-static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l56)
+static int cs35l56_sync_asp1_mixer_widgets_with_firmware(struct cs35l56_private *cs35l56)
 {
        struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cs35l56->component);
        const char *prefix = cs35l56->component->name_prefix;
@@ -135,13 +81,19 @@ static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l5
        unsigned int val[4];
        int i, item, ret;
 
+       if (cs35l56->asp1_mixer_widgets_initialized)
+               return 0;
+
        /*
         * Resume so we can read the registers from silicon if the regmap
         * cache has not yet been populated.
         */
        ret = pm_runtime_resume_and_get(cs35l56->base.dev);
        if (ret < 0)
-               return;
+               return ret;
+
+       /* Wait for firmware download and reboot */
+       cs35l56_wait_dsp_ready(cs35l56);
 
        ret = regmap_bulk_read(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT,
                               val, ARRAY_SIZE(val));
@@ -151,12 +103,9 @@ static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l5
 
        if (ret) {
                dev_err(cs35l56->base.dev, "Failed to read ASP1 mixer regs: %d\n", ret);
-               return;
+               return ret;
        }
 
-       snd_soc_card_mutex_lock(dapm->card);
-       WARN_ON(!dapm->card->instantiated);
-
        for (i = 0; i < ARRAY_SIZE(cs35l56_asp1_mux_control_names); ++i) {
                name = cs35l56_asp1_mux_control_names[i];
 
@@ -176,16 +125,65 @@ static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l5
                snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL);
        }
 
-       snd_soc_card_mutex_unlock(dapm->card);
+       cs35l56->asp1_mixer_widgets_initialized = true;
+
+       return 0;
 }
 
-static void cs35l56_mux_init_work(struct work_struct *work)
+static int cs35l56_dspwait_asp1tx_get(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
 {
-       struct cs35l56_private *cs35l56 = container_of(work,
-                                                      struct cs35l56_private,
-                                                      mux_init_work);
+       struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
+       struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       int index = e->shift_l;
+       unsigned int addr, val;
+       int ret;
+
+       ret = cs35l56_sync_asp1_mixer_widgets_with_firmware(cs35l56);
+       if (ret)
+               return ret;
+
+       addr = cs35l56_asp1_mixer_regs[index];
+       ret = regmap_read(cs35l56->base.regmap, addr, &val);
+       if (ret)
+               return ret;
+
+       val &= CS35L56_ASP_TXn_SRC_MASK;
+       ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);
+
+       return 0;
+}
+
+static int cs35l56_dspwait_asp1tx_put(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
+       struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
+       struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       int item = ucontrol->value.enumerated.item[0];
+       int index = e->shift_l;
+       unsigned int addr, val;
+       bool changed;
+       int ret;
 
-       cs35l56_mark_asp1_mixer_widgets_dirty(cs35l56);
+       ret = cs35l56_sync_asp1_mixer_widgets_with_firmware(cs35l56);
+       if (ret)
+               return ret;
+
+       addr = cs35l56_asp1_mixer_regs[index];
+       val = snd_soc_enum_item_to_val(e, item);
+
+       ret = regmap_update_bits_check(cs35l56->base.regmap, addr,
+                                      CS35L56_ASP_TXn_SRC_MASK, val, &changed);
+       if (ret)
+               return ret;
+
+       if (changed)
+               snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL);
+
+       return changed;
 }
 
 static DECLARE_TLV_DB_SCALE(vol_tlv, -10000, 25, 0);
@@ -936,14 +934,6 @@ static void cs35l56_dsp_work(struct work_struct *work)
        else
                cs35l56_patch(cs35l56, firmware_missing);
 
-
-       /*
-        * Set starting value of ASP1 mux widgets. Updating a mux takes
-        * the DAPM mutex. Post this to a separate job so that DAPM
-        * power-up can wait for dsp_work to complete without deadlocking
-        * on the DAPM mutex.
-        */
-       queue_work(cs35l56->dsp_wq, &cs35l56->mux_init_work);
 err:
        pm_runtime_mark_last_busy(cs35l56->base.dev);
        pm_runtime_put_autosuspend(cs35l56->base.dev);
@@ -989,6 +979,13 @@ static int cs35l56_component_probe(struct snd_soc_component *component)
        debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->base.can_hibernate);
        debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->base.fw_patched);
 
+       /*
+        * The widgets for the ASP1TX mixer can't be initialized
+        * until the firmware has been downloaded and rebooted.
+        */
+       regcache_drop_region(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT, CS35L56_ASP1TX4_INPUT);
+       cs35l56->asp1_mixer_widgets_initialized = false;
+
        queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work);
 
        return 0;
@@ -999,7 +996,6 @@ static void cs35l56_component_remove(struct snd_soc_component *component)
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
 
        cancel_work_sync(&cs35l56->dsp_work);
-       cancel_work_sync(&cs35l56->mux_init_work);
 
        if (cs35l56->dsp.cs_dsp.booted)
                wm_adsp_power_down(&cs35l56->dsp);
@@ -1070,10 +1066,8 @@ int cs35l56_system_suspend(struct device *dev)
 
        dev_dbg(dev, "system_suspend\n");
 
-       if (cs35l56->component) {
+       if (cs35l56->component)
                flush_work(&cs35l56->dsp_work);
-               cancel_work_sync(&cs35l56->mux_init_work);
-       }
 
        /*
         * The interrupt line is normally shared, but after we start suspending
@@ -1224,7 +1218,6 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56)
                return -ENOMEM;
 
        INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work);
-       INIT_WORK(&cs35l56->mux_init_work, cs35l56_mux_init_work);
 
        dsp = &cs35l56->dsp;
        cs35l56_init_cs_dsp(&cs35l56->base, &dsp->cs_dsp);
@@ -1269,6 +1262,94 @@ static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56)
        return 0;
 }
 
+/*
+ * Some SoundWire laptops have a spk-id-gpios property but it points to
+ * the wrong ACPI Device node so can't be used to get the GPIO. Try to
+ * find the SDCA node containing the GpioIo resource and add a GPIO
+ * mapping to it.
+ */
+static const struct acpi_gpio_params cs35l56_af01_first_gpio = { 0, 0, false };
+static const struct acpi_gpio_mapping cs35l56_af01_spkid_gpios_mapping[] = {
+       { "spk-id-gpios", &cs35l56_af01_first_gpio, 1 },
+       { }
+};
+
+static void cs35l56_acpi_dev_release_driver_gpios(void *adev)
+{
+       acpi_dev_remove_driver_gpios(adev);
+}
+
+static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l56)
+{
+       struct fwnode_handle *af01_fwnode;
+       const union acpi_object *obj;
+       struct gpio_desc *desc;
+       int ret;
+
+       /* Find the SDCA node containing the GpioIo */
+       af01_fwnode = device_get_named_child_node(cs35l56->base.dev, "AF01");
+       if (!af01_fwnode) {
+               dev_dbg(cs35l56->base.dev, "No AF01 node\n");
+               return -ENOENT;
+       }
+
+       ret = acpi_dev_get_property(ACPI_COMPANION(cs35l56->base.dev),
+                                   "spk-id-gpios", ACPI_TYPE_PACKAGE, &obj);
+       if (ret) {
+               dev_dbg(cs35l56->base.dev, "Could not get spk-id-gpios package: %d\n", ret);
+               return -ENOENT;
+       }
+
+       /* The broken properties we can handle are a 4-element package (one GPIO) */
+       if (obj->package.count != 4) {
+               dev_warn(cs35l56->base.dev, "Unexpected spk-id element count %d\n",
+                        obj->package.count);
+               return -ENOENT;
+       }
+
+       /* Add a GPIO mapping if it doesn't already have one */
+       if (!fwnode_property_present(af01_fwnode, "spk-id-gpios")) {
+               struct acpi_device *adev = to_acpi_device_node(af01_fwnode);
+
+               /*
+                * Can't use devm_acpi_dev_add_driver_gpios() because the
+                * mapping isn't being added to the node pointed to by
+                * ACPI_COMPANION().
+                */
+               ret = acpi_dev_add_driver_gpios(adev, cs35l56_af01_spkid_gpios_mapping);
+               if (ret) {
+                       return dev_err_probe(cs35l56->base.dev, ret,
+                                            "Failed to add gpio mapping to AF01\n");
+               }
+
+               ret = devm_add_action_or_reset(cs35l56->base.dev,
+                                              cs35l56_acpi_dev_release_driver_gpios,
+                                              adev);
+               if (ret)
+                       return ret;
+
+               dev_dbg(cs35l56->base.dev, "Added spk-id-gpios mapping to AF01\n");
+       }
+
+       desc = fwnode_gpiod_get_index(af01_fwnode, "spk-id", 0, GPIOD_IN, NULL);
+       if (IS_ERR(desc)) {
+               ret = PTR_ERR(desc);
+               return dev_err_probe(cs35l56->base.dev, ret, "Get GPIO from AF01 failed\n");
+       }
+
+       ret = gpiod_get_value_cansleep(desc);
+       gpiod_put(desc);
+
+       if (ret < 0) {
+               dev_err_probe(cs35l56->base.dev, ret, "Error reading spk-id GPIO\n");
+               return ret;
+               }
+
+       dev_info(cs35l56->base.dev, "Got spk-id from AF01\n");
+
+       return ret;
+}
+
 int cs35l56_common_probe(struct cs35l56_private *cs35l56)
 {
        int ret;
@@ -1313,6 +1394,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
        }
 
        ret = cs35l56_get_speaker_id(&cs35l56->base);
+       if (ACPI_COMPANION(cs35l56->base.dev) && cs35l56->sdw_peripheral && (ret == -ENOENT))
+               ret = cs35l56_try_get_broken_sdca_spkid_gpio(cs35l56);
+
        if ((ret < 0) && (ret != -ENOENT))
                goto err;
 
index 596b141e3f9612389cae4c6b80eab20f4f90fd69..b000e7365e4065eaffc3b3ea2aa2714b9acccdfd 100644 (file)
@@ -34,7 +34,6 @@ struct cs35l56_private {
        struct wm_adsp dsp; /* must be first member */
        struct cs35l56_base base;
        struct work_struct dsp_work;
-       struct work_struct mux_init_work;
        struct workqueue_struct *dsp_wq;
        struct snd_soc_component *component;
        struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES];
@@ -52,6 +51,7 @@ struct cs35l56_private {
        u8 asp_slot_count;
        bool tdm_mode;
        bool sysclk_set;
+       bool asp1_mixer_widgets_initialized;
        u8 old_sdw_clock_scale;
 };
 
index 6a64681767de8122d06bee23b5a21674d930bf57..a97ccb512deba86305ff433fa5b639fdfbb8dcbe 100644 (file)
@@ -2257,7 +2257,10 @@ static int cs42l43_codec_probe(struct platform_device *pdev)
        pm_runtime_use_autosuspend(priv->dev);
        pm_runtime_set_active(priv->dev);
        pm_runtime_get_noresume(priv->dev);
-       devm_pm_runtime_enable(priv->dev);
+
+       ret = devm_pm_runtime_enable(priv->dev);
+       if (ret)
+               goto err_pm;
 
        for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) {
                ret = cs42l43_request_irq(priv, dom, cs42l43_irqs[i].name,
@@ -2333,8 +2336,47 @@ static int cs42l43_codec_runtime_resume(struct device *dev)
        return 0;
 }
 
-static DEFINE_RUNTIME_DEV_PM_OPS(cs42l43_codec_pm_ops, NULL,
-                                cs42l43_codec_runtime_resume, NULL);
+static int cs42l43_codec_suspend(struct device *dev)
+{
+       struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+
+       disable_irq(cs42l43->irq);
+
+       return 0;
+}
+
+static int cs42l43_codec_suspend_noirq(struct device *dev)
+{
+       struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+
+       enable_irq(cs42l43->irq);
+
+       return 0;
+}
+
+static int cs42l43_codec_resume(struct device *dev)
+{
+       struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+
+       enable_irq(cs42l43->irq);
+
+       return 0;
+}
+
+static int cs42l43_codec_resume_noirq(struct device *dev)
+{
+       struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+
+       disable_irq(cs42l43->irq);
+
+       return 0;
+}
+
+static const struct dev_pm_ops cs42l43_codec_pm_ops = {
+       SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend, cs42l43_codec_resume)
+       NOIRQ_SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend_noirq, cs42l43_codec_resume_noirq)
+       RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL)
+};
 
 static const struct platform_device_id cs42l43_codec_id_table[] = {
        { "cs42l43-codec", },
index 5150d6ee374810f34a881dd33d4ea57187e13522..20191a4473c2d2c7b4ae6bddf34109a403b84e3d 100644 (file)
@@ -3317,6 +3317,7 @@ static void rt5645_jack_detect_work(struct work_struct *work)
                                    report, SND_JACK_HEADPHONE);
                snd_soc_jack_report(rt5645->mic_jack,
                                    report, SND_JACK_MICROPHONE);
+               mutex_unlock(&rt5645->jd_mutex);
                return;
        case 4:
                val = snd_soc_component_read(rt5645->component, RT5645_A_JD_CTRL1) & 0x0020;
@@ -3692,6 +3693,11 @@ static const struct rt5645_platform_data jd_mode3_monospk_platform_data = {
        .mono_speaker = true,
 };
 
+static const struct rt5645_platform_data jd_mode3_inv_data = {
+       .jd_mode = 3,
+       .inv_jd1_1 = true,
+};
+
 static const struct rt5645_platform_data jd_mode3_platform_data = {
        .jd_mode = 3,
 };
@@ -3837,6 +3843,16 @@ static const struct dmi_system_id dmi_platform_data[] = {
                  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
                  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
                  DMI_EXACT_MATCH(DMI_BOARD_VERSION, "Default string"),
+                 /*
+                  * Above strings are too generic, LattePanda BIOS versions for
+                  * all 4 hw revisions are:
+                  * DF-BI-7-S70CR100-*
+                  * DF-BI-7-S70CR110-*
+                  * DF-BI-7-S70CR200-*
+                  * LP-BS-7-S70CR700-*
+                  * Do a partial match for S70CR to avoid false positive matches.
+                  */
+                 DMI_MATCH(DMI_BIOS_VERSION, "S70CR"),
                },
                .driver_data = (void *)&lattepanda_board_platform_data,
        },
@@ -3871,6 +3887,16 @@ static const struct dmi_system_id dmi_platform_data[] = {
                },
                .driver_data = (void *)&intel_braswell_platform_data,
        },
+       {
+               .ident = "Meegopad T08",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Default string"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
+                       DMI_MATCH(DMI_BOARD_NAME, "T3 MRD"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "V1.1"),
+               },
+               .driver_data = (void *)&jd_mode3_inv_data,
+       },
        { }
 };
 
index b7e56ceb1acff9f41e6a26f09e1c4395ff537553..5d0e5348b361a568475fd1fde3a299a57926b365 100644 (file)
@@ -267,6 +267,7 @@ void tas2781_reset(struct tasdevice_priv *tas_dev)
 EXPORT_SYMBOL_GPL(tas2781_reset);
 
 int tascodec_init(struct tasdevice_priv *tas_priv, void *codec,
+       struct module *module,
        void (*cont)(const struct firmware *fw, void *context))
 {
        int ret = 0;
@@ -280,7 +281,7 @@ int tascodec_init(struct tasdevice_priv *tas_priv, void *codec,
                tas_priv->dev_name, tas_priv->ndev);
        crc8_populate_msb(tas_priv->crc8_lkp_tbl, TASDEVICE_CRC8_POLYNOMIAL);
        tas_priv->codec = codec;
-       ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
+       ret = request_firmware_nowait(module, FW_ACTION_UEVENT,
                tas_priv->rca_binaryname, tas_priv->dev, GFP_KERNEL, tas_priv,
                cont);
        if (ret)
index 32913bd1a623381ee6e8d3d72c3f8e49d60ff0f7..b5abff230e43701f0f00c7b19f895469305747d7 100644 (file)
@@ -566,7 +566,7 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec)
 {
        struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
 
-       return tascodec_init(tas_priv, codec, tasdevice_fw_ready);
+       return tascodec_init(tas_priv, codec, THIS_MODULE, tasdevice_fw_ready);
 }
 
 static void tasdevice_deinit(void *context)
index 59c3793f65df0c5573ec6e7f873ef33d31f46371..db78eb2f0108071736b6bafa5e77f874b15f3375 100644 (file)
@@ -477,6 +477,9 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
        return 0;
 
 err_i915_init:
+       pci_free_irq(pci, 0, adev);
+       pci_free_irq(pci, 0, bus);
+       pci_free_irq_vectors(pci);
        pci_clear_master(pci);
        pci_set_drvdata(pci, NULL);
 err_acquire_irq:
index 778236d3fd2806912120ab0eb953f96a6c79c90b..48b3c67c91032c97b7da54e9d822876f0e66b994 100644 (file)
@@ -857,7 +857,7 @@ assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcf
        }
 
        /* If topology sets value don't overwrite it */
-       if (cfg->copier.vindex.i2s.instance)
+       if (cfg->copier.vindex.val)
                return;
 
        mach = dev_get_platdata(comp->card->dev);
index 10a84a2c1036e9ce67751702a047795a5eabf9b7..c014d85a08b24755682f3faf97e3e60cd171dc7a 100644 (file)
@@ -241,7 +241,8 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev)
 
        /* fix index of codec dai */
        for (i = 0; i < ARRAY_SIZE(byt_cht_cx2072x_dais); i++) {
-               if (!strcmp(byt_cht_cx2072x_dais[i].codecs->name,
+               if (byt_cht_cx2072x_dais[i].codecs->name &&
+                   !strcmp(byt_cht_cx2072x_dais[i].codecs->name,
                            "i2c-14F10720:00")) {
                        dai_index = i;
                        break;
index 7e5eea690023dff7bbdea996c739428c28445cf9..f4ac3ddd148b83757881426a2522adacd3d966d3 100644 (file)
@@ -245,7 +245,8 @@ static int bytcht_da7213_probe(struct platform_device *pdev)
 
        /* fix index of codec dai */
        for (i = 0; i < ARRAY_SIZE(dailink); i++) {
-               if (!strcmp(dailink[i].codecs->name, "i2c-DLGS7213:00")) {
+               if (dailink[i].codecs->name &&
+                   !strcmp(dailink[i].codecs->name, "i2c-DLGS7213:00")) {
                        dai_index = i;
                        break;
                }
index 1564a88a885efa1838317f453bf3d514a529d7e8..2fcec2e02bb53b403350ee76cb124ed99882087e 100644 (file)
@@ -546,7 +546,8 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
 
        /* fix index of codec dai */
        for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) {
-               if (!strcmp(byt_cht_es8316_dais[i].codecs->name,
+               if (byt_cht_es8316_dais[i].codecs->name &&
+                   !strcmp(byt_cht_es8316_dais[i].codecs->name,
                            "i2c-ESSX8316:00")) {
                        dai_index = i;
                        break;
index 42466b4b1ca45e159ea40c42809018929e0ed0dc..03be5e26ec4ab5472efc14c58c5fd5939743f3fa 100644 (file)
@@ -1652,7 +1652,8 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
 
        /* fix index of codec dai */
        for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {
-               if (!strcmp(byt_rt5640_dais[i].codecs->name,
+               if (byt_rt5640_dais[i].codecs->name &&
+                   !strcmp(byt_rt5640_dais[i].codecs->name,
                            "i2c-10EC5640:00")) {
                        dai_index = i;
                        break;
index f9fe8414f454ff481b7e1b84f5377bb4d8835161..80c841b000a311229c310fec3ba91264696e6025 100644 (file)
@@ -910,7 +910,8 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
 
        /* fix index of codec dai */
        for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) {
-               if (!strcmp(byt_rt5651_dais[i].codecs->name,
+               if (byt_rt5651_dais[i].codecs->name &&
+                   !strcmp(byt_rt5651_dais[i].codecs->name,
                            "i2c-10EC5651:00")) {
                        dai_index = i;
                        break;
index 6978ebde669357fc7a25abc9961aaafc278b1789..cccb5e90c0fefc6a888ac302a63ed50a9423342d 100644 (file)
@@ -605,7 +605,8 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
 
        /* find index of codec dai */
        for (i = 0; i < ARRAY_SIZE(byt_wm5102_dais); i++) {
-               if (!strcmp(byt_wm5102_dais[i].codecs->name,
+               if (byt_wm5102_dais[i].codecs->name &&
+                   !strcmp(byt_wm5102_dais[i].codecs->name,
                            "wm5102-codec")) {
                        dai_index = i;
                        break;
index c952a96cde7ebe27ba6f61ed6d417d0f063d0e1e..eb41b7115d01dd38685d5a10cd393e46eb4106a4 100644 (file)
@@ -40,7 +40,6 @@ struct cht_acpi_card {
 struct cht_mc_private {
        struct snd_soc_jack jack;
        struct cht_acpi_card *acpi_card;
-       char codec_name[SND_ACPI_I2C_ID_LEN];
        struct clk *mclk;
 };
 
@@ -567,14 +566,14 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
        }
 
        card->dev = &pdev->dev;
-       sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id);
 
        /* set correct codec name */
        for (i = 0; i < ARRAY_SIZE(cht_dailink); i++)
-               if (!strcmp(card->dai_link[i].codecs->name,
+               if (cht_dailink[i].codecs->name &&
+                   !strcmp(cht_dailink[i].codecs->name,
                            "i2c-10EC5645:00")) {
-                       card->dai_link[i].codecs->name = drv->codec_name;
                        dai_index = i;
+                       break;
                }
 
        /* fixup codec name based on HID */
index 8cf0b33cc02eb5763acbb572ab0387efbe8da325..be2d1a8dbca807dd1f4af070382d2d2f169c9e27 100644 (file)
@@ -466,7 +466,8 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
 
        /* find index of codec dai */
        for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
-               if (!strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) {
+               if (cht_dailink[i].codecs->name &&
+                   !strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) {
                        dai_index = i;
                        break;
                }
index 052e40cb38feca032752784545a4a07332369054..00bbd291be5cea4b5f43ee06b85b55dfb8eb91c2 100644 (file)
@@ -123,7 +123,7 @@ static struct snd_pcm_hardware q6apm_dai_hardware_playback = {
        .fifo_size =            0,
 };
 
-static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv)
+static void event_handler(uint32_t opcode, uint32_t token, void *payload, void *priv)
 {
        struct q6apm_dai_rtd *prtd = priv;
        struct snd_pcm_substream *substream = prtd->substream;
@@ -157,7 +157,7 @@ static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, vo
 }
 
 static void event_handler_compr(uint32_t opcode, uint32_t token,
-                               uint32_t *payload, void *priv)
+                               void *payload, void *priv)
 {
        struct q6apm_dai_rtd *prtd = priv;
        struct snd_compr_stream *substream = prtd->cstream;
@@ -352,7 +352,7 @@ static int q6apm_dai_open(struct snd_soc_component *component,
 
        spin_lock_init(&prtd->lock);
        prtd->substream = substream;
-       prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler, prtd, graph_id);
+       prtd->graph = q6apm_graph_open(dev, event_handler, prtd, graph_id);
        if (IS_ERR(prtd->graph)) {
                dev_err(dev, "%s: Could not allocate memory\n", __func__);
                ret = PTR_ERR(prtd->graph);
@@ -496,7 +496,7 @@ static int q6apm_dai_compr_open(struct snd_soc_component *component,
                return -ENOMEM;
 
        prtd->cstream = stream;
-       prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler_compr, prtd, graph_id);
+       prtd->graph = q6apm_graph_open(dev, event_handler_compr, prtd, graph_id);
        if (IS_ERR(prtd->graph)) {
                ret = PTR_ERR(prtd->graph);
                kfree(prtd);
index 2743f07a5e0811912722d174bd4096950e788a62..b44b1b1adb6ed9e913c857168902f00949abcb86 100644 (file)
@@ -188,11 +188,13 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
 
        dsp_ack = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write);
        if (dsp_ack) {
+               spin_lock_irq(&sdev->ipc_lock);
                /* handle immediate reply from DSP core */
                acp_dsp_ipc_get_reply(sdev);
                snd_sof_ipc_reply(sdev, 0);
                /* set the done bit */
                acp_dsp_ipc_dsp_done(sdev);
+               spin_unlock_irq(&sdev->ipc_lock);
                ipc_irq = true;
        }
 
index 32a741fcb84fffcc3988e4deabf4e99ef4863d49..07632ae6ccf5ec058565d50f1992475795c490d2 100644 (file)
@@ -355,21 +355,20 @@ static irqreturn_t acp_irq_thread(int irq, void *context)
        unsigned int count = ACP_HW_SEM_RETRY_COUNT;
 
        spin_lock_irq(&sdev->ipc_lock);
-       while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) {
-               /* Wait until acquired HW Semaphore lock or timeout */
-               count--;
-               if (!count) {
-                       dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__);
-                       spin_unlock_irq(&sdev->ipc_lock);
-                       return IRQ_NONE;
-               }
+       /* Wait until acquired HW Semaphore lock or timeout */
+       while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset) && --count)
+               ;
+       spin_unlock_irq(&sdev->ipc_lock);
+
+       if (!count) {
+               dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__);
+               return IRQ_NONE;
        }
 
        sof_ops(sdev)->irq_thread(irq, sdev);
        /* Unlock or Release HW Semaphore */
        snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0);
 
-       spin_unlock_irq(&sdev->ipc_lock);
        return IRQ_HANDLED;
 };
 
index 78a57eb9cbc377c0b525827a0539baea6850ca6f..b26ffe767fab553467897b4facc13931668b27fe 100644 (file)
@@ -36,7 +36,7 @@ static const struct sof_dev_desc lnl_desc = {
                [SOF_IPC_TYPE_4] = "intel/sof-ipc4/lnl",
        },
        .default_tplg_path = {
-               [SOF_IPC_TYPE_4] = "intel/sof-ace-tplg",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
        .default_fw_filename = {
                [SOF_IPC_TYPE_4] = "sof-lnl.ri",
index 0660d4b2ac96b66da5997d1aed60ddb91341571a..a361ee9d1107f5ed7533d1f71400f95ae4ad34af 100644 (file)
@@ -33,18 +33,18 @@ static const struct sof_dev_desc tgl_desc = {
        .dspless_mode_supported = true,         /* Only supported for HDaudio */
        .default_fw_path = {
                [SOF_IPC_TYPE_3] = "intel/sof",
-               [SOF_IPC_TYPE_4] = "intel/avs/tgl",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4/tgl",
        },
        .default_lib_path = {
-               [SOF_IPC_TYPE_4] = "intel/avs-lib/tgl",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/tgl",
        },
        .default_tplg_path = {
                [SOF_IPC_TYPE_3] = "intel/sof-tplg",
-               [SOF_IPC_TYPE_4] = "intel/avs-tplg",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
        .default_fw_filename = {
                [SOF_IPC_TYPE_3] = "sof-tgl.ri",
-               [SOF_IPC_TYPE_4] = "dsp_basefw.bin",
+               [SOF_IPC_TYPE_4] = "sof-tgl.ri",
        },
        .nocodec_tplg_filename = "sof-tgl-nocodec.tplg",
        .ops = &sof_tgl_ops,
@@ -66,18 +66,18 @@ static const struct sof_dev_desc tglh_desc = {
        .dspless_mode_supported = true,         /* Only supported for HDaudio */
        .default_fw_path = {
                [SOF_IPC_TYPE_3] = "intel/sof",
-               [SOF_IPC_TYPE_4] = "intel/avs/tgl-h",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4/tgl-h",
        },
        .default_lib_path = {
-               [SOF_IPC_TYPE_4] = "intel/avs-lib/tgl-h",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/tgl-h",
        },
        .default_tplg_path = {
                [SOF_IPC_TYPE_3] = "intel/sof-tplg",
-               [SOF_IPC_TYPE_4] = "intel/avs-tplg",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
        .default_fw_filename = {
                [SOF_IPC_TYPE_3] = "sof-tgl-h.ri",
-               [SOF_IPC_TYPE_4] = "dsp_basefw.bin",
+               [SOF_IPC_TYPE_4] = "sof-tgl-h.ri",
        },
        .nocodec_tplg_filename = "sof-tgl-nocodec.tplg",
        .ops = &sof_tgl_ops,
@@ -98,18 +98,18 @@ static const struct sof_dev_desc ehl_desc = {
        .dspless_mode_supported = true,         /* Only supported for HDaudio */
        .default_fw_path = {
                [SOF_IPC_TYPE_3] = "intel/sof",
-               [SOF_IPC_TYPE_4] = "intel/avs/ehl",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4/ehl",
        },
        .default_lib_path = {
-               [SOF_IPC_TYPE_4] = "intel/avs-lib/ehl",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/ehl",
        },
        .default_tplg_path = {
                [SOF_IPC_TYPE_3] = "intel/sof-tplg",
-               [SOF_IPC_TYPE_4] = "intel/avs-tplg",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
        .default_fw_filename = {
                [SOF_IPC_TYPE_3] = "sof-ehl.ri",
-               [SOF_IPC_TYPE_4] = "dsp_basefw.bin",
+               [SOF_IPC_TYPE_4] = "sof-ehl.ri",
        },
        .nocodec_tplg_filename = "sof-ehl-nocodec.tplg",
        .ops = &sof_tgl_ops,
@@ -131,18 +131,18 @@ static const struct sof_dev_desc adls_desc = {
        .dspless_mode_supported = true,         /* Only supported for HDaudio */
        .default_fw_path = {
                [SOF_IPC_TYPE_3] = "intel/sof",
-               [SOF_IPC_TYPE_4] = "intel/avs/adl-s",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4/adl-s",
        },
        .default_lib_path = {
-               [SOF_IPC_TYPE_4] = "intel/avs-lib/adl-s",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/adl-s",
        },
        .default_tplg_path = {
                [SOF_IPC_TYPE_3] = "intel/sof-tplg",
-               [SOF_IPC_TYPE_4] = "intel/avs-tplg",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
        .default_fw_filename = {
                [SOF_IPC_TYPE_3] = "sof-adl-s.ri",
-               [SOF_IPC_TYPE_4] = "dsp_basefw.bin",
+               [SOF_IPC_TYPE_4] = "sof-adl-s.ri",
        },
        .nocodec_tplg_filename = "sof-adl-nocodec.tplg",
        .ops = &sof_tgl_ops,
@@ -164,18 +164,18 @@ static const struct sof_dev_desc adl_desc = {
        .dspless_mode_supported = true,         /* Only supported for HDaudio */
        .default_fw_path = {
                [SOF_IPC_TYPE_3] = "intel/sof",
-               [SOF_IPC_TYPE_4] = "intel/avs/adl",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4/adl",
        },
        .default_lib_path = {
-               [SOF_IPC_TYPE_4] = "intel/avs-lib/adl",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/adl",
        },
        .default_tplg_path = {
                [SOF_IPC_TYPE_3] = "intel/sof-tplg",
-               [SOF_IPC_TYPE_4] = "intel/avs-tplg",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
        .default_fw_filename = {
                [SOF_IPC_TYPE_3] = "sof-adl.ri",
-               [SOF_IPC_TYPE_4] = "dsp_basefw.bin",
+               [SOF_IPC_TYPE_4] = "sof-adl.ri",
        },
        .nocodec_tplg_filename = "sof-adl-nocodec.tplg",
        .ops = &sof_tgl_ops,
@@ -197,18 +197,18 @@ static const struct sof_dev_desc adl_n_desc = {
        .dspless_mode_supported = true,         /* Only supported for HDaudio */
        .default_fw_path = {
                [SOF_IPC_TYPE_3] = "intel/sof",
-               [SOF_IPC_TYPE_4] = "intel/avs/adl-n",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4/adl-n",
        },
        .default_lib_path = {
-               [SOF_IPC_TYPE_4] = "intel/avs-lib/adl-n",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/adl-n",
        },
        .default_tplg_path = {
                [SOF_IPC_TYPE_3] = "intel/sof-tplg",
-               [SOF_IPC_TYPE_4] = "intel/avs-tplg",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
        .default_fw_filename = {
                [SOF_IPC_TYPE_3] = "sof-adl-n.ri",
-               [SOF_IPC_TYPE_4] = "dsp_basefw.bin",
+               [SOF_IPC_TYPE_4] = "sof-adl-n.ri",
        },
        .nocodec_tplg_filename = "sof-adl-nocodec.tplg",
        .ops = &sof_tgl_ops,
@@ -230,18 +230,18 @@ static const struct sof_dev_desc rpls_desc = {
        .dspless_mode_supported = true,         /* Only supported for HDaudio */
        .default_fw_path = {
                [SOF_IPC_TYPE_3] = "intel/sof",
-               [SOF_IPC_TYPE_4] = "intel/avs/rpl-s",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4/rpl-s",
        },
        .default_lib_path = {
-               [SOF_IPC_TYPE_4] = "intel/avs-lib/rpl-s",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/rpl-s",
        },
        .default_tplg_path = {
                [SOF_IPC_TYPE_3] = "intel/sof-tplg",
-               [SOF_IPC_TYPE_4] = "intel/avs-tplg",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
        .default_fw_filename = {
                [SOF_IPC_TYPE_3] = "sof-rpl-s.ri",
-               [SOF_IPC_TYPE_4] = "dsp_basefw.bin",
+               [SOF_IPC_TYPE_4] = "sof-rpl-s.ri",
        },
        .nocodec_tplg_filename = "sof-rpl-nocodec.tplg",
        .ops = &sof_tgl_ops,
@@ -263,18 +263,18 @@ static const struct sof_dev_desc rpl_desc = {
        .dspless_mode_supported = true,         /* Only supported for HDaudio */
        .default_fw_path = {
                [SOF_IPC_TYPE_3] = "intel/sof",
-               [SOF_IPC_TYPE_4] = "intel/avs/rpl",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4/rpl",
        },
        .default_lib_path = {
-               [SOF_IPC_TYPE_4] = "intel/avs-lib/rpl",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/rpl",
        },
        .default_tplg_path = {
                [SOF_IPC_TYPE_3] = "intel/sof-tplg",
-               [SOF_IPC_TYPE_4] = "intel/avs-tplg",
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
        .default_fw_filename = {
                [SOF_IPC_TYPE_3] = "sof-rpl.ri",
-               [SOF_IPC_TYPE_4] = "dsp_basefw.bin",
+               [SOF_IPC_TYPE_4] = "sof-rpl.ri",
        },
        .nocodec_tplg_filename = "sof-rpl-nocodec.tplg",
        .ops = &sof_tgl_ops,
index a8832a1c1a2442c8af573943787e3b6768b5e36f..d47698f4be2deb6f5bb943e2de2611923c45c387 100644 (file)
@@ -2360,27 +2360,16 @@ static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev)
        return 0;
 }
 
-/*
- * For older firmware, this function doesn't free widgets for static pipelines during suspend.
- * It only resets use_count for all widgets.
- */
-static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify)
+static int sof_ipc3_free_widgets_in_list(struct snd_sof_dev *sdev, bool include_scheduler,
+                                        bool *dyn_widgets, bool verify)
 {
        struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
        struct snd_sof_widget *swidget;
-       struct snd_sof_route *sroute;
-       bool dyn_widgets = false;
        int ret;
 
-       /*
-        * This function is called during suspend and for one-time topology verification during
-        * first boot. In both cases, there is no need to protect swidget->use_count and
-        * sroute->setup because during suspend all running streams are suspended and during
-        * topology loading the sound card unavailable to open PCMs.
-        */
        list_for_each_entry(swidget, &sdev->widget_list, list) {
                if (swidget->dynamic_pipeline_widget) {
-                       dyn_widgets = true;
+                       *dyn_widgets = true;
                        continue;
                }
 
@@ -2395,11 +2384,49 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif
                        continue;
                }
 
+               if (include_scheduler && swidget->id != snd_soc_dapm_scheduler)
+                       continue;
+
+               if (!include_scheduler && swidget->id == snd_soc_dapm_scheduler)
+                       continue;
+
                ret = sof_widget_free(sdev, swidget);
                if (ret < 0)
                        return ret;
        }
 
+       return 0;
+}
+
+/*
+ * For older firmware, this function doesn't free widgets for static pipelines during suspend.
+ * It only resets use_count for all widgets.
+ */
+static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify)
+{
+       struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
+       struct snd_sof_widget *swidget;
+       struct snd_sof_route *sroute;
+       bool dyn_widgets = false;
+       int ret;
+
+       /*
+        * This function is called during suspend and for one-time topology verification during
+        * first boot. In both cases, there is no need to protect swidget->use_count and
+        * sroute->setup because during suspend all running streams are suspended and during
+        * topology loading the sound card unavailable to open PCMs. Do not free the scheduler
+        * widgets yet so that the secondary cores do not get powered down before all the widgets
+        * associated with the scheduler are freed.
+        */
+       ret = sof_ipc3_free_widgets_in_list(sdev, false, &dyn_widgets, verify);
+       if (ret < 0)
+               return ret;
+
+       /* free all the scheduler widgets now */
+       ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify);
+       if (ret < 0)
+               return ret;
+
        /*
         * Tear down all pipelines associated with PCMs that did not get suspended
         * and unset the prepare flag so that they can be set up again during resume.
index fb40378ad0840255a9b35cb74f99c9b80d5271b9..c03dd513fbff142fee51a9b0233920024d691f1d 100644 (file)
@@ -1067,7 +1067,7 @@ static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev)
                return;
        }
 
-       if (hdr.size < sizeof(hdr)) {
+       if (hdr.size < sizeof(hdr) || hdr.size > SOF_IPC_MSG_MAX_SIZE) {
                dev_err(sdev->dev, "The received message size is invalid\n");
                return;
        }
index 85d3f390e4b290774687086f37b2a73473117e54..07eb5c6d4adf3246877e4881c1927a6a4f8c39ee 100644 (file)
@@ -413,7 +413,18 @@ skip_pause_transition:
        ret = sof_ipc4_set_multi_pipeline_state(sdev, state, trigger_list);
        if (ret < 0) {
                dev_err(sdev->dev, "failed to set final state %d for all pipelines\n", state);
-               goto free;
+               /*
+                * workaround: if the firmware is crashed while setting the
+                * pipelines to reset state we must ignore the error code and
+                * reset it to 0.
+                * Since the firmware is crashed we will not send IPC messages
+                * and we are going to see errors printed, but the state of the
+                * widgets will be correct for the next boot.
+                */
+               if (sdev->fw_state != SOF_FW_CRASHED || state != SOF_IPC4_PIPE_RESET)
+                       goto free;
+
+               ret = 0;
        }
 
        /* update RUNNING/RESET state for all pipelines that were just triggered */
index 6b0993258e039b052b9196f3a2f43f720623f2ce..c1f2e5a03de969af932b3f8394332eb6f80983a3 100644 (file)
@@ -1742,50 +1742,44 @@ static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number,
        }
 }
 
-static struct usb_midi_in_jack_descriptor *find_usb_in_jack_descriptor(
-                                       struct usb_host_interface *hostif, uint8_t jack_id)
+/* return iJack for the corresponding jackID */
+static int find_usb_ijack(struct usb_host_interface *hostif, uint8_t jack_id)
 {
        unsigned char *extra = hostif->extra;
        int extralen = hostif->extralen;
+       struct usb_descriptor_header *h;
+       struct usb_midi_out_jack_descriptor *outjd;
+       struct usb_midi_in_jack_descriptor *injd;
+       size_t sz;
 
        while (extralen > 4) {
-               struct usb_midi_in_jack_descriptor *injd =
-                               (struct usb_midi_in_jack_descriptor *)extra;
+               h = (struct usb_descriptor_header *)extra;
+               if (h->bDescriptorType != USB_DT_CS_INTERFACE)
+                       goto next;
 
+               outjd = (struct usb_midi_out_jack_descriptor *)h;
+               if (h->bLength >= sizeof(*outjd) &&
+                   outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK &&
+                   outjd->bJackID == jack_id) {
+                       sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins);
+                       if (outjd->bLength < sz)
+                               goto next;
+                       return *(extra + sz - 1);
+               }
+
+               injd = (struct usb_midi_in_jack_descriptor *)h;
                if (injd->bLength >= sizeof(*injd) &&
-                   injd->bDescriptorType == USB_DT_CS_INTERFACE &&
                    injd->bDescriptorSubtype == UAC_MIDI_IN_JACK &&
-                               injd->bJackID == jack_id)
-                       return injd;
-               if (!extra[0])
-                       break;
-               extralen -= extra[0];
-               extra += extra[0];
-       }
-       return NULL;
-}
-
-static struct usb_midi_out_jack_descriptor *find_usb_out_jack_descriptor(
-                                       struct usb_host_interface *hostif, uint8_t jack_id)
-{
-       unsigned char *extra = hostif->extra;
-       int extralen = hostif->extralen;
+                   injd->bJackID == jack_id)
+                       return injd->iJack;
 
-       while (extralen > 4) {
-               struct usb_midi_out_jack_descriptor *outjd =
-                               (struct usb_midi_out_jack_descriptor *)extra;
-
-               if (outjd->bLength >= sizeof(*outjd) &&
-                   outjd->bDescriptorType == USB_DT_CS_INTERFACE &&
-                   outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK &&
-                               outjd->bJackID == jack_id)
-                       return outjd;
+next:
                if (!extra[0])
                        break;
                extralen -= extra[0];
                extra += extra[0];
        }
-       return NULL;
+       return 0;
 }
 
 static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
@@ -1796,13 +1790,10 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
        const char *name_format;
        struct usb_interface *intf;
        struct usb_host_interface *hostif;
-       struct usb_midi_in_jack_descriptor *injd;
-       struct usb_midi_out_jack_descriptor *outjd;
        uint8_t jack_name_buf[32];
        uint8_t *default_jack_name = "MIDI";
        uint8_t *jack_name = default_jack_name;
        uint8_t iJack;
-       size_t sz;
        int res;
 
        struct snd_rawmidi_substream *substream =
@@ -1816,21 +1807,7 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
        intf = umidi->iface;
        if (intf && jack_id >= 0) {
                hostif = intf->cur_altsetting;
-               iJack = 0;
-               if (stream != SNDRV_RAWMIDI_STREAM_OUTPUT) {
-                       /* in jacks connect to outs */
-                       outjd = find_usb_out_jack_descriptor(hostif, jack_id);
-                       if (outjd) {
-                               sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins);
-                               if (outjd->bLength >= sz)
-                                       iJack = *(((uint8_t *) outjd) + sz - sizeof(uint8_t));
-                       }
-               } else {
-                       /* and out jacks connect to ins */
-                       injd = find_usb_in_jack_descriptor(hostif, jack_id);
-                       if (injd)
-                               iJack = injd->iJack;
-               }
+               iJack = find_usb_ijack(hostif, jack_id);
                if (iJack != 0) {
                        res = usb_string(umidi->dev, iJack, jack_name_buf,
                          ARRAY_SIZE(jack_name_buf));
index 11ff975242cac7cff4dfaab3a4591dc4cb82eb1d..e2ff22b379a44c584b7325249c48db9b3368c7d8 100644 (file)
@@ -4,7 +4,7 @@
 
 #define __GEN_RMWcc(fullop, var, cc, ...)                              \
 do {                                                                   \
-       asm_volatile_goto (fullop "; j" cc " %l[cc_label]"              \
+       asm goto (fullop "; j" cc " %l[cc_label]"               \
                        : : "m" (var), ## __VA_ARGS__                   \
                        : "memory" : cc_label);                         \
        return 0;                                                       \
index 1bdd834bdd57198059c91222036314403191cdbc..d09f9dc172a486875e2e62cf8550a69f24c9beed 100644 (file)
@@ -36,8 +36,8 @@
 #include <linux/compiler-gcc.h>
 #endif
 
-#ifndef asm_volatile_goto
-#define asm_volatile_goto(x...) asm goto(x)
+#ifndef asm_goto_output
+#define asm_goto_output(x...) asm goto(x)
 #endif
 
 #endif /* __LINUX_COMPILER_TYPES_H */
index 534576f06df1cc78f63619d873f77ad0390f45e5..c59e4adb905df61494db41d99355fbac5d742bab 100644 (file)
@@ -12,6 +12,7 @@
 #include <syscall.h>
 #include <unistd.h>
 #include <sys/resource.h>
+#include <linux/close_range.h>
 
 #include "../kselftest_harness.h"
 #include "../clone3/clone3_selftests.h"
index b07af2a4c4de0b680f37d510337d38b23691a478..7fae90293a9d88278ae9b6202758dfe08b4d7899 100755 (executable)
@@ -33,8 +33,8 @@ if [[ ! -d "${PDT}" ]]; then
 fi
 
 nodes_compatible=$(
-       for node_compat in $(find ${PDT} -name compatible); do
-               node=$(dirname "${node_compat}")
+       for node in $(find ${PDT} -type d); do
+               [ ! -f "${node}"/compatible ] && continue
                # Check if node is available
                if [[ -e "${node}"/status ]]; then
                        status=$(tr -d '\000' < "${node}"/status)
@@ -46,10 +46,11 @@ nodes_compatible=$(
 
 nodes_dev_bound=$(
        IFS=$'\n'
-       for uevent in $(find /sys/devices -name uevent); do
-               if [[ -d "$(dirname "${uevent}")"/driver ]]; then
-                       grep '^OF_FULLNAME=' "${uevent}" | sed -e 's|OF_FULLNAME=||'
-               fi
+       for dev_dir in $(find /sys/devices -type d); do
+               [ ! -f "${dev_dir}"/uevent ] && continue
+               [ ! -d "${dev_dir}"/driver ] && continue
+
+               grep '^OF_FULLNAME=' "${dev_dir}"/uevent | sed -e 's|OF_FULLNAME=||'
        done
        )
 
index 274b8465b42a5aa1d210ced625db7ce42799e693..2cb8dd1f8275fb0a83e1a4cb605e7b63c46ef221 100644 (file)
@@ -248,7 +248,7 @@ static void *test_vcpu_run(void *arg)
                REPORT_GUEST_ASSERT(uc);
                break;
        default:
-               TEST_FAIL("Unexpected guest exit\n");
+               TEST_FAIL("Unexpected guest exit");
        }
 
        return NULL;
@@ -287,7 +287,7 @@ static int test_migrate_vcpu(unsigned int vcpu_idx)
 
        /* Allow the error where the vCPU thread is already finished */
        TEST_ASSERT(ret == 0 || ret == ESRCH,
-                   "Failed to migrate the vCPU:%u to pCPU: %u; ret: %d\n",
+                   "Failed to migrate the vCPU:%u to pCPU: %u; ret: %d",
                    vcpu_idx, new_pcpu, ret);
 
        return ret;
@@ -326,12 +326,12 @@ static void test_run(struct kvm_vm *vm)
 
        pthread_mutex_init(&vcpu_done_map_lock, NULL);
        vcpu_done_map = bitmap_zalloc(test_args.nr_vcpus);
-       TEST_ASSERT(vcpu_done_map, "Failed to allocate vcpu done bitmap\n");
+       TEST_ASSERT(vcpu_done_map, "Failed to allocate vcpu done bitmap");
 
        for (i = 0; i < (unsigned long)test_args.nr_vcpus; i++) {
                ret = pthread_create(&pt_vcpu_run[i], NULL, test_vcpu_run,
                                     (void *)(unsigned long)i);
-               TEST_ASSERT(!ret, "Failed to create vCPU-%d pthread\n", i);
+               TEST_ASSERT(!ret, "Failed to create vCPU-%d pthread", i);
        }
 
        /* Spawn a thread to control the vCPU migrations */
@@ -340,7 +340,7 @@ static void test_run(struct kvm_vm *vm)
 
                ret = pthread_create(&pt_vcpu_migration, NULL,
                                        test_vcpu_migration, NULL);
-               TEST_ASSERT(!ret, "Failed to create the migration pthread\n");
+               TEST_ASSERT(!ret, "Failed to create the migration pthread");
        }
 
 
@@ -384,7 +384,7 @@ static struct kvm_vm *test_vm_create(void)
                if (kvm_has_cap(KVM_CAP_COUNTER_OFFSET))
                        vm_ioctl(vm, KVM_ARM_SET_COUNTER_OFFSET, &test_args.offset);
                else
-                       TEST_FAIL("no support for global offset\n");
+                       TEST_FAIL("no support for global offset");
        }
 
        for (i = 0; i < nr_vcpus; i++)
index 31f66ba97228babe46bf2c46640077065ded7241..27c10e7a7e0124f01e0e636dfb25944c0d7abc95 100644 (file)
@@ -175,18 +175,18 @@ static void test_fw_regs_before_vm_start(struct kvm_vcpu *vcpu)
                /* First 'read' should be an upper limit of the features supported */
                vcpu_get_reg(vcpu, reg_info->reg, &val);
                TEST_ASSERT(val == FW_REG_ULIMIT_VAL(reg_info->max_feat_bit),
-                       "Expected all the features to be set for reg: 0x%lx; expected: 0x%lx; read: 0x%lx\n",
+                       "Expected all the features to be set for reg: 0x%lx; expected: 0x%lx; read: 0x%lx",
                        reg_info->reg, FW_REG_ULIMIT_VAL(reg_info->max_feat_bit), val);
 
                /* Test a 'write' by disabling all the features of the register map */
                ret = __vcpu_set_reg(vcpu, reg_info->reg, 0);
                TEST_ASSERT(ret == 0,
-                       "Failed to clear all the features of reg: 0x%lx; ret: %d\n",
+                       "Failed to clear all the features of reg: 0x%lx; ret: %d",
                        reg_info->reg, errno);
 
                vcpu_get_reg(vcpu, reg_info->reg, &val);
                TEST_ASSERT(val == 0,
-                       "Expected all the features to be cleared for reg: 0x%lx\n", reg_info->reg);
+                       "Expected all the features to be cleared for reg: 0x%lx", reg_info->reg);
 
                /*
                 * Test enabling a feature that's not supported.
@@ -195,7 +195,7 @@ static void test_fw_regs_before_vm_start(struct kvm_vcpu *vcpu)
                if (reg_info->max_feat_bit < 63) {
                        ret = __vcpu_set_reg(vcpu, reg_info->reg, BIT(reg_info->max_feat_bit + 1));
                        TEST_ASSERT(ret != 0 && errno == EINVAL,
-                       "Unexpected behavior or return value (%d) while setting an unsupported feature for reg: 0x%lx\n",
+                       "Unexpected behavior or return value (%d) while setting an unsupported feature for reg: 0x%lx",
                        errno, reg_info->reg);
                }
        }
@@ -216,7 +216,7 @@ static void test_fw_regs_after_vm_start(struct kvm_vcpu *vcpu)
                 */
                vcpu_get_reg(vcpu, reg_info->reg, &val);
                TEST_ASSERT(val == 0,
-                       "Expected all the features to be cleared for reg: 0x%lx\n",
+                       "Expected all the features to be cleared for reg: 0x%lx",
                        reg_info->reg);
 
                /*
@@ -226,7 +226,7 @@ static void test_fw_regs_after_vm_start(struct kvm_vcpu *vcpu)
                 */
                ret = __vcpu_set_reg(vcpu, reg_info->reg, FW_REG_ULIMIT_VAL(reg_info->max_feat_bit));
                TEST_ASSERT(ret != 0 && errno == EBUSY,
-               "Unexpected behavior or return value (%d) while setting a feature while VM is running for reg: 0x%lx\n",
+               "Unexpected behavior or return value (%d) while setting a feature while VM is running for reg: 0x%lx",
                errno, reg_info->reg);
        }
 }
@@ -265,7 +265,7 @@ static void test_guest_stage(struct kvm_vm **vm, struct kvm_vcpu **vcpu)
        case TEST_STAGE_HVC_IFACE_FALSE_INFO:
                break;
        default:
-               TEST_FAIL("Unknown test stage: %d\n", prev_stage);
+               TEST_FAIL("Unknown test stage: %d", prev_stage);
        }
 }
 
@@ -294,7 +294,7 @@ static void test_run(void)
                        REPORT_GUEST_ASSERT(uc);
                        break;
                default:
-                       TEST_FAIL("Unexpected guest exit\n");
+                       TEST_FAIL("Unexpected guest exit");
                }
        }
 
index 08a5ca5bed56a9f602c01c024b19771a5cc9e219..53fddad57cbbc689231fd81cd1947d27f1c84807 100644 (file)
@@ -414,10 +414,10 @@ static bool punch_hole_in_backing_store(struct kvm_vm *vm,
        if (fd != -1) {
                ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
                                0, paging_size);
-               TEST_ASSERT(ret == 0, "fallocate failed\n");
+               TEST_ASSERT(ret == 0, "fallocate failed");
        } else {
                ret = madvise(hva, paging_size, MADV_DONTNEED);
-               TEST_ASSERT(ret == 0, "madvise failed\n");
+               TEST_ASSERT(ret == 0, "madvise failed");
        }
 
        return true;
@@ -501,7 +501,7 @@ static bool handle_cmd(struct kvm_vm *vm, int cmd)
 
 void fail_vcpu_run_no_handler(int ret)
 {
-       TEST_FAIL("Unexpected vcpu run failure\n");
+       TEST_FAIL("Unexpected vcpu run failure");
 }
 
 void fail_vcpu_run_mmio_no_syndrome_handler(int ret)
index f4ceae9c89257d211bab149be149510898e02290..2d189f3da228cdb74b8a8976c0736abde18ce9b5 100644 (file)
@@ -178,7 +178,7 @@ static void expect_call_denied(struct kvm_vcpu *vcpu)
        struct ucall uc;
 
        if (get_ucall(vcpu, &uc) != UCALL_SYNC)
-               TEST_FAIL("Unexpected ucall: %lu\n", uc.cmd);
+               TEST_FAIL("Unexpected ucall: %lu", uc.cmd);
 
        TEST_ASSERT(uc.args[1] == SMCCC_RET_NOT_SUPPORTED,
                    "Unexpected SMCCC return code: %lu", uc.args[1]);
index 9d51b56913496ed38f0413183b49380aba017ba3..5f9713364693b4eacd175bad2b1531e6a91f5504 100644 (file)
@@ -517,11 +517,11 @@ static void test_create_vpmu_vm_with_pmcr_n(uint64_t pmcr_n, bool expect_fail)
 
        if (expect_fail)
                TEST_ASSERT(pmcr_orig == pmcr,
-                           "PMCR.N modified by KVM to a larger value (PMCR: 0x%lx) for pmcr_n: 0x%lx\n",
+                           "PMCR.N modified by KVM to a larger value (PMCR: 0x%lx) for pmcr_n: 0x%lx",
                            pmcr, pmcr_n);
        else
                TEST_ASSERT(pmcr_n == get_pmcr_n(pmcr),
-                           "Failed to update PMCR.N to %lu (received: %lu)\n",
+                           "Failed to update PMCR.N to %lu (received: %lu)",
                            pmcr_n, get_pmcr_n(pmcr));
 }
 
@@ -594,12 +594,12 @@ static void run_pmregs_validity_test(uint64_t pmcr_n)
                 */
                vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(set_reg_id), &reg_val);
                TEST_ASSERT((reg_val & (~valid_counters_mask)) == 0,
-                           "Initial read of set_reg: 0x%llx has unimplemented counters enabled: 0x%lx\n",
+                           "Initial read of set_reg: 0x%llx has unimplemented counters enabled: 0x%lx",
                            KVM_ARM64_SYS_REG(set_reg_id), reg_val);
 
                vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(clr_reg_id), &reg_val);
                TEST_ASSERT((reg_val & (~valid_counters_mask)) == 0,
-                           "Initial read of clr_reg: 0x%llx has unimplemented counters enabled: 0x%lx\n",
+                           "Initial read of clr_reg: 0x%llx has unimplemented counters enabled: 0x%lx",
                            KVM_ARM64_SYS_REG(clr_reg_id), reg_val);
 
                /*
@@ -611,12 +611,12 @@ static void run_pmregs_validity_test(uint64_t pmcr_n)
 
                vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(set_reg_id), &reg_val);
                TEST_ASSERT((reg_val & (~valid_counters_mask)) == 0,
-                           "Read of set_reg: 0x%llx has unimplemented counters enabled: 0x%lx\n",
+                           "Read of set_reg: 0x%llx has unimplemented counters enabled: 0x%lx",
                            KVM_ARM64_SYS_REG(set_reg_id), reg_val);
 
                vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(clr_reg_id), &reg_val);
                TEST_ASSERT((reg_val & (~valid_counters_mask)) == 0,
-                           "Read of clr_reg: 0x%llx has unimplemented counters enabled: 0x%lx\n",
+                           "Read of clr_reg: 0x%llx has unimplemented counters enabled: 0x%lx",
                            KVM_ARM64_SYS_REG(clr_reg_id), reg_val);
        }
 
index 09c116a82a8499d7b14dc60bdcb088dd6c6914c7..bf3609f718544fb2b5d6c116d8eec4b28c29ab98 100644 (file)
@@ -45,10 +45,10 @@ static void vcpu_worker(struct memstress_vcpu_args *vcpu_args)
 
        /* Let the guest access its memory */
        ret = _vcpu_run(vcpu);
-       TEST_ASSERT(ret == 0, "vcpu_run failed: %d\n", ret);
+       TEST_ASSERT(ret == 0, "vcpu_run failed: %d", ret);
        if (get_ucall(vcpu, NULL) != UCALL_SYNC) {
                TEST_ASSERT(false,
-                           "Invalid guest sync status: exit_reason=%s\n",
+                           "Invalid guest sync status: exit_reason=%s",
                            exit_reason_str(run->exit_reason));
        }
 
index d374dbcf9a535dbd9efc7316e9c63c4152010e7a..504f6fe980e8fd7bf57ae105ed574fd3bf62d583 100644 (file)
@@ -88,9 +88,9 @@ static void vcpu_worker(struct memstress_vcpu_args *vcpu_args)
                ret = _vcpu_run(vcpu);
                ts_diff = timespec_elapsed(start);
 
-               TEST_ASSERT(ret == 0, "vcpu_run failed: %d\n", ret);
+               TEST_ASSERT(ret == 0, "vcpu_run failed: %d", ret);
                TEST_ASSERT(get_ucall(vcpu, NULL) == UCALL_SYNC,
-                           "Invalid guest sync status: exit_reason=%s\n",
+                           "Invalid guest sync status: exit_reason=%s",
                            exit_reason_str(run->exit_reason));
 
                pr_debug("Got sync event from vCPU %d\n", vcpu_idx);
index 6cbecf4997676f327095a399a75dcfa514fca13c..eaad5b20854ccf095a4447245554f8ecd48e0506 100644 (file)
@@ -262,7 +262,7 @@ static void default_after_vcpu_run(struct kvm_vcpu *vcpu, int ret, int err)
                    "vcpu run failed: errno=%d", err);
 
        TEST_ASSERT(get_ucall(vcpu, NULL) == UCALL_SYNC,
-                   "Invalid guest sync status: exit_reason=%s\n",
+                   "Invalid guest sync status: exit_reason=%s",
                    exit_reason_str(run->exit_reason));
 
        vcpu_handle_sync_stop();
@@ -376,7 +376,10 @@ static void dirty_ring_collect_dirty_pages(struct kvm_vcpu *vcpu, int slot,
 
        cleared = kvm_vm_reset_dirty_ring(vcpu->vm);
 
-       /* Cleared pages should be the same as collected */
+       /*
+        * Cleared pages should be the same as collected, as KVM is supposed to
+        * clear only the entries that have been harvested.
+        */
        TEST_ASSERT(cleared == count, "Reset dirty pages (%u) mismatch "
                    "with collected (%u)", cleared, count);
 
@@ -410,17 +413,11 @@ static void dirty_ring_after_vcpu_run(struct kvm_vcpu *vcpu, int ret, int err)
                pr_info("vcpu continues now.\n");
        } else {
                TEST_ASSERT(false, "Invalid guest sync status: "
-                           "exit_reason=%s\n",
+                           "exit_reason=%s",
                            exit_reason_str(run->exit_reason));
        }
 }
 
-static void dirty_ring_before_vcpu_join(void)
-{
-       /* Kick another round of vcpu just to make sure it will quit */
-       sem_post(&sem_vcpu_cont);
-}
-
 struct log_mode {
        const char *name;
        /* Return true if this mode is supported, otherwise false */
@@ -433,7 +430,6 @@ struct log_mode {
                                     uint32_t *ring_buf_idx);
        /* Hook to call when after each vcpu run */
        void (*after_vcpu_run)(struct kvm_vcpu *vcpu, int ret, int err);
-       void (*before_vcpu_join) (void);
 } log_modes[LOG_MODE_NUM] = {
        {
                .name = "dirty-log",
@@ -452,7 +448,6 @@ struct log_mode {
                .supported = dirty_ring_supported,
                .create_vm_done = dirty_ring_create_vm_done,
                .collect_dirty_pages = dirty_ring_collect_dirty_pages,
-               .before_vcpu_join = dirty_ring_before_vcpu_join,
                .after_vcpu_run = dirty_ring_after_vcpu_run,
        },
 };
@@ -513,14 +508,6 @@ static void log_mode_after_vcpu_run(struct kvm_vcpu *vcpu, int ret, int err)
                mode->after_vcpu_run(vcpu, ret, err);
 }
 
-static void log_mode_before_vcpu_join(void)
-{
-       struct log_mode *mode = &log_modes[host_log_mode];
-
-       if (mode->before_vcpu_join)
-               mode->before_vcpu_join();
-}
-
 static void generate_random_array(uint64_t *guest_array, uint64_t size)
 {
        uint64_t i;
@@ -719,6 +706,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
        struct kvm_vm *vm;
        unsigned long *bmap;
        uint32_t ring_buf_idx = 0;
+       int sem_val;
 
        if (!log_mode_supported()) {
                print_skip("Log mode '%s' not supported",
@@ -788,12 +776,22 @@ static void run_test(enum vm_guest_mode mode, void *arg)
        /* Start the iterations */
        iteration = 1;
        sync_global_to_guest(vm, iteration);
-       host_quit = false;
+       WRITE_ONCE(host_quit, false);
        host_dirty_count = 0;
        host_clear_count = 0;
        host_track_next_count = 0;
        WRITE_ONCE(dirty_ring_vcpu_ring_full, false);
 
+       /*
+        * Ensure the previous iteration didn't leave a dangling semaphore, i.e.
+        * that the main task and vCPU worker were synchronized and completed
+        * verification of all iterations.
+        */
+       sem_getvalue(&sem_vcpu_stop, &sem_val);
+       TEST_ASSERT_EQ(sem_val, 0);
+       sem_getvalue(&sem_vcpu_cont, &sem_val);
+       TEST_ASSERT_EQ(sem_val, 0);
+
        pthread_create(&vcpu_thread, NULL, vcpu_worker, vcpu);
 
        while (iteration < p->iterations) {
@@ -819,15 +817,21 @@ static void run_test(enum vm_guest_mode mode, void *arg)
                assert(host_log_mode == LOG_MODE_DIRTY_RING ||
                       atomic_read(&vcpu_sync_stop_requested) == false);
                vm_dirty_log_verify(mode, bmap);
-               sem_post(&sem_vcpu_cont);
 
-               iteration++;
+               /*
+                * Set host_quit before sem_vcpu_cont in the final iteration to
+                * ensure that the vCPU worker doesn't resume the guest.  As
+                * above, the dirty ring test may stop and wait even when not
+                * explicitly request to do so, i.e. would hang waiting for a
+                * "continue" if it's allowed to resume the guest.
+                */
+               if (++iteration == p->iterations)
+                       WRITE_ONCE(host_quit, true);
+
+               sem_post(&sem_vcpu_cont);
                sync_global_to_guest(vm, iteration);
        }
 
-       /* Tell the vcpu thread to quit */
-       host_quit = true;
-       log_mode_before_vcpu_join();
        pthread_join(vcpu_thread, NULL);
 
        pr_info("Total bits checked: dirty (%"PRIu64"), clear (%"PRIu64"), "
index 8274ef04301f6704528293206603efca9690b29c..91f05f78e8249124332e9a28fef53daf4e746fd1 100644 (file)
@@ -152,7 +152,7 @@ static void check_supported(struct vcpu_reg_list *c)
                        continue;
 
                __TEST_REQUIRE(kvm_has_cap(s->capability),
-                              "%s: %s not available, skipping tests\n",
+                              "%s: %s not available, skipping tests",
                               config_name(c), s->name);
        }
 }
index 41230b74619023d447f48fc8555936e194ce9387..3502caa3590c6488442a015ff40e5fa1027e41e6 100644 (file)
@@ -98,7 +98,7 @@ static void ucall_abort(const char *assert_msg, const char *expected_assert_msg)
        int offset = len_str - len_substr;
 
        TEST_ASSERT(len_substr <= len_str,
-                   "Expected '%s' to be a substring of '%s'\n",
+                   "Expected '%s' to be a substring of '%s'",
                    assert_msg, expected_assert_msg);
 
        TEST_ASSERT(strcmp(&assert_msg[offset], expected_assert_msg) == 0,
@@ -116,7 +116,7 @@ static void run_test(struct kvm_vcpu *vcpu, const char *expected_printf,
                vcpu_run(vcpu);
 
                TEST_ASSERT(run->exit_reason == UCALL_EXIT_REASON,
-                           "Unexpected exit reason: %u (%s),\n",
+                           "Unexpected exit reason: %u (%s),",
                            run->exit_reason, exit_reason_str(run->exit_reason));
 
                switch (get_ucall(vcpu, &uc)) {
@@ -161,11 +161,11 @@ static void test_limits(void)
        vcpu_run(vcpu);
 
        TEST_ASSERT(run->exit_reason == UCALL_EXIT_REASON,
-                   "Unexpected exit reason: %u (%s),\n",
+                   "Unexpected exit reason: %u (%s),",
                    run->exit_reason, exit_reason_str(run->exit_reason));
 
        TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_ABORT,
-                   "Unexpected ucall command: %lu,  Expected: %u (UCALL_ABORT)\n",
+                   "Unexpected ucall command: %lu,  Expected: %u (UCALL_ABORT)",
                    uc.cmd, UCALL_ABORT);
 
        kvm_vm_free(vm);
index f5d59b9934f184163e3e1e48578508d2a5255eae..decc521fc7603b1440cbb414f94acdf042ce1c5a 100644 (file)
@@ -41,7 +41,7 @@ static void *run_vcpu(void *arg)
 
        vcpu_run(vcpu);
 
-       TEST_ASSERT(false, "%s: exited with reason %d: %s\n",
+       TEST_ASSERT(false, "%s: exited with reason %d: %s",
                    __func__, run->exit_reason,
                    exit_reason_str(run->exit_reason));
        pthread_exit(NULL);
@@ -55,7 +55,7 @@ static void *sleeping_thread(void *arg)
                fd = open("/dev/null", O_RDWR);
                close(fd);
        }
-       TEST_ASSERT(false, "%s: exited\n", __func__);
+       TEST_ASSERT(false, "%s: exited", __func__);
        pthread_exit(NULL);
 }
 
@@ -118,7 +118,7 @@ static void run_test(uint32_t run)
        for (i = 0; i < VCPU_NUM; ++i)
                check_join(threads[i], &b);
        /* Should not be reached */
-       TEST_ASSERT(false, "%s: [%d] child escaped the ninja\n", __func__, run);
+       TEST_ASSERT(false, "%s: [%d] child escaped the ninja", __func__, run);
 }
 
 void wait_for_child_setup(pid_t pid)
index 71a41fa924b7d09cb1a3aaf9bcc779d7d3311110..50a5e31ba8da1bc904d7cb04be2571bf786b847e 100644 (file)
@@ -195,4 +195,6 @@ __printf(3, 4) int guest_snprintf(char *buf, int n, const char *fmt, ...);
 
 char *strdup_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2), nonnull(1)));
 
+char *sys_get_cur_clocksource(void);
+
 #endif /* SELFTEST_KVM_TEST_UTIL_H */
index a84863503fcb46cda532840f3be4512cf35061c3..5bca8c947c8253819dd07ed6266a03194a0c1857 100644 (file)
@@ -1271,4 +1271,6 @@ void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
 #define PFERR_GUEST_PAGE_MASK  BIT_ULL(PFERR_GUEST_PAGE_BIT)
 #define PFERR_IMPLICIT_ACCESS  BIT_ULL(PFERR_IMPLICIT_ACCESS_BIT)
 
+bool sys_clocksource_is_based_on_tsc(void);
+
 #endif /* SELFTEST_KVM_PROCESSOR_H */
index 31b3cb24b9a75cdf0cc9e71f1f0cf820ec20edae..b9e23265e4b3833a4fa07acca1461fb35cd8297f 100644 (file)
@@ -65,7 +65,7 @@ int main(int argc, char *argv[])
 
                        int r = setrlimit(RLIMIT_NOFILE, &rl);
                        __TEST_REQUIRE(r >= 0,
-                                      "RLIMIT_NOFILE hard limit is too low (%d, wanted %d)\n",
+                                      "RLIMIT_NOFILE hard limit is too low (%d, wanted %d)",
                                       old_rlim_max, nr_fds_wanted);
                } else {
                        TEST_ASSERT(!setrlimit(RLIMIT_NOFILE, &rl), "setrlimit() failed!");
index e37dc9c21888f4bc4ed06bf3bacff89e28c68b5d..e0ba97ac1c5611a386981caf679b12910b600d8b 100644 (file)
@@ -204,9 +204,9 @@ static void *vcpu_worker(void *data)
                ret = _vcpu_run(vcpu);
                ts_diff = timespec_elapsed(start);
 
-               TEST_ASSERT(ret == 0, "vcpu_run failed: %d\n", ret);
+               TEST_ASSERT(ret == 0, "vcpu_run failed: %d", ret);
                TEST_ASSERT(get_ucall(vcpu, NULL) == UCALL_SYNC,
-                           "Invalid guest sync status: exit_reason=%s\n",
+                           "Invalid guest sync status: exit_reason=%s",
                            exit_reason_str(vcpu->run->exit_reason));
 
                pr_debug("Got sync event from vCPU %d\n", vcpu->id);
index 41c776b642c0cd0be722e4bad1e0e9cc1f0cff80..43b9a72833602e072ad7ba5e7e69c341fb8469a6 100644 (file)
@@ -398,7 +398,7 @@ void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
        int i;
 
        TEST_ASSERT(num >= 1 && num <= 8, "Unsupported number of args,\n"
-                   "  num: %u\n", num);
+                   "  num: %u", num);
 
        va_start(ap, num);
 
index b5f28d21a947704456b3e8cc9a0e86825d386c2f..184378d593e9a8e45ca7d46e6116ca692d710abd 100644 (file)
@@ -38,7 +38,7 @@ int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs,
        struct list_head *iter;
        unsigned int nr_gic_pages, nr_vcpus_created = 0;
 
-       TEST_ASSERT(nr_vcpus, "Number of vCPUs cannot be empty\n");
+       TEST_ASSERT(nr_vcpus, "Number of vCPUs cannot be empty");
 
        /*
         * Make sure that the caller is infact calling this
@@ -47,7 +47,7 @@ int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs,
        list_for_each(iter, &vm->vcpus)
                nr_vcpus_created++;
        TEST_ASSERT(nr_vcpus == nr_vcpus_created,
-                       "Number of vCPUs requested (%u) doesn't match with the ones created for the VM (%u)\n",
+                       "Number of vCPUs requested (%u) doesn't match with the ones created for the VM (%u)",
                        nr_vcpus, nr_vcpus_created);
 
        /* Distributor setup */
index 266f3876e10aff98955b6301d4e0ddaa3236e26e..f34d926d9735913f5ba826a8bee07aa0b8169d43 100644 (file)
@@ -184,7 +184,7 @@ void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename)
                                "Seek to program segment offset failed,\n"
                                "  program header idx: %u errno: %i\n"
                                "  offset_rv: 0x%jx\n"
-                               "  expected: 0x%jx\n",
+                               "  expected: 0x%jx",
                                n1, errno, (intmax_t) offset_rv,
                                (intmax_t) phdr.p_offset);
                        test_read(fd, addr_gva2hva(vm, phdr.p_vaddr),
index e066d584c65611b4da45b0312734c3fab7b3dcd6..1b197426f29fcd1e6faf4abe3069044dfe64b9ca 100644 (file)
@@ -27,7 +27,8 @@ int open_path_or_exit(const char *path, int flags)
        int fd;
 
        fd = open(path, flags);
-       __TEST_REQUIRE(fd >= 0, "%s not available (errno: %d)", path, errno);
+       __TEST_REQUIRE(fd >= 0 || errno != ENOENT, "Cannot open %s: %s", path, strerror(errno));
+       TEST_ASSERT(fd >= 0, "Failed to open '%s'", path);
 
        return fd;
 }
@@ -320,7 +321,7 @@ static uint64_t vm_nr_pages_required(enum vm_guest_mode mode,
        uint64_t nr_pages;
 
        TEST_ASSERT(nr_runnable_vcpus,
-                   "Use vm_create_barebones() for VMs that _never_ have vCPUs\n");
+                   "Use vm_create_barebones() for VMs that _never_ have vCPUs");
 
        TEST_ASSERT(nr_runnable_vcpus <= kvm_check_cap(KVM_CAP_MAX_VCPUS),
                    "nr_vcpus = %d too large for host, max-vcpus = %d",
@@ -491,7 +492,7 @@ void kvm_pin_this_task_to_pcpu(uint32_t pcpu)
        CPU_ZERO(&mask);
        CPU_SET(pcpu, &mask);
        r = sched_setaffinity(0, sizeof(mask), &mask);
-       TEST_ASSERT(!r, "sched_setaffinity() failed for pCPU '%u'.\n", pcpu);
+       TEST_ASSERT(!r, "sched_setaffinity() failed for pCPU '%u'.", pcpu);
 }
 
 static uint32_t parse_pcpu(const char *cpu_str, const cpu_set_t *allowed_mask)
@@ -499,7 +500,7 @@ static uint32_t parse_pcpu(const char *cpu_str, const cpu_set_t *allowed_mask)
        uint32_t pcpu = atoi_non_negative("CPU number", cpu_str);
 
        TEST_ASSERT(CPU_ISSET(pcpu, allowed_mask),
-                   "Not allowed to run on pCPU '%d', check cgroups?\n", pcpu);
+                   "Not allowed to run on pCPU '%d', check cgroups?", pcpu);
        return pcpu;
 }
 
@@ -529,7 +530,7 @@ void kvm_parse_vcpu_pinning(const char *pcpus_string, uint32_t vcpu_to_pcpu[],
        int i, r;
 
        cpu_list = strdup(pcpus_string);
-       TEST_ASSERT(cpu_list, "strdup() allocation failed.\n");
+       TEST_ASSERT(cpu_list, "strdup() allocation failed.");
 
        r = sched_getaffinity(0, sizeof(allowed_mask), &allowed_mask);
        TEST_ASSERT(!r, "sched_getaffinity() failed");
@@ -538,7 +539,7 @@ void kvm_parse_vcpu_pinning(const char *pcpus_string, uint32_t vcpu_to_pcpu[],
 
        /* 1. Get all pcpus for vcpus. */
        for (i = 0; i < nr_vcpus; i++) {
-               TEST_ASSERT(cpu, "pCPU not provided for vCPU '%d'\n", i);
+               TEST_ASSERT(cpu, "pCPU not provided for vCPU '%d'", i);
                vcpu_to_pcpu[i] = parse_pcpu(cpu, &allowed_mask);
                cpu = strtok(NULL, delim);
        }
@@ -1057,7 +1058,7 @@ void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,
        TEST_ASSERT(ret == 0, "KVM_SET_USER_MEMORY_REGION2 IOCTL failed,\n"
                "  rc: %i errno: %i\n"
                "  slot: %u flags: 0x%x\n"
-               "  guest_phys_addr: 0x%lx size: 0x%lx guest_memfd: %d\n",
+               "  guest_phys_addr: 0x%lx size: 0x%lx guest_memfd: %d",
                ret, errno, slot, flags,
                guest_paddr, (uint64_t) region->region.memory_size,
                region->region.guest_memfd);
@@ -1222,7 +1223,7 @@ void vm_guest_mem_fallocate(struct kvm_vm *vm, uint64_t base, uint64_t size,
                len = min_t(uint64_t, end - gpa, region->region.memory_size - offset);
 
                ret = fallocate(region->region.guest_memfd, mode, fd_offset, len);
-               TEST_ASSERT(!ret, "fallocate() failed to %s at %lx (len = %lu), fd = %d, mode = %x, offset = %lx\n",
+               TEST_ASSERT(!ret, "fallocate() failed to %s at %lx (len = %lu), fd = %d, mode = %x, offset = %lx",
                            punch_hole ? "punch hole" : "allocate", gpa, len,
                            region->region.guest_memfd, mode, fd_offset);
        }
@@ -1265,7 +1266,7 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
        struct kvm_vcpu *vcpu;
 
        /* Confirm a vcpu with the specified id doesn't already exist. */
-       TEST_ASSERT(!vcpu_exists(vm, vcpu_id), "vCPU%d already exists\n", vcpu_id);
+       TEST_ASSERT(!vcpu_exists(vm, vcpu_id), "vCPU%d already exists", vcpu_id);
 
        /* Allocate and initialize new vcpu structure. */
        vcpu = calloc(1, sizeof(*vcpu));
index d05487e5a371df1d17c96d4fbec1b1f6b2e60c0f..cf2c739713080f3f55e1383fb5d0a9e65f5d1dc7 100644 (file)
@@ -192,7 +192,7 @@ struct kvm_vm *memstress_create_vm(enum vm_guest_mode mode, int nr_vcpus,
        TEST_ASSERT(guest_num_pages < region_end_gfn,
                    "Requested more guest memory than address space allows.\n"
                    "    guest pages: %" PRIx64 " max gfn: %" PRIx64
-                   " nr_vcpus: %d wss: %" PRIx64 "]\n",
+                   " nr_vcpus: %d wss: %" PRIx64 "]",
                    guest_num_pages, region_end_gfn - 1, nr_vcpus, vcpu_memory_bytes);
 
        args->gpa = (region_end_gfn - guest_num_pages - 1) * args->guest_page_size;
index 7ca736fb4194046072bf69b3210f0fefd8ce0834..2bb33a8ac03c25f622ec6dc21430529b8b128a9d 100644 (file)
@@ -327,7 +327,7 @@ void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
        int i;
 
        TEST_ASSERT(num >= 1 && num <= 8, "Unsupported number of args,\n"
-                   "  num: %u\n", num);
+                   "  num: %u", num);
 
        va_start(ap, num);
 
index 15945121daf17dc46bf38cf8f2a24d23b8f073f3..f6d227892cbcfc88cc97abcc9a0d78b2aa38f459 100644 (file)
@@ -198,7 +198,7 @@ void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
        int i;
 
        TEST_ASSERT(num >= 1 && num <= 5, "Unsupported number of args,\n"
-                   "  num: %u\n",
+                   "  num: %u",
                    num);
 
        va_start(ap, num);
index 5d7f28b02d73bab79891b808bb46c095c52bd505..5a8f8becb12984ff52a16f01281b5d396ce318be 100644 (file)
@@ -392,3 +392,28 @@ char *strdup_printf(const char *fmt, ...)
 
        return str;
 }
+
+#define CLOCKSOURCE_PATH "/sys/devices/system/clocksource/clocksource0/current_clocksource"
+
+char *sys_get_cur_clocksource(void)
+{
+       char *clk_name;
+       struct stat st;
+       FILE *fp;
+
+       fp = fopen(CLOCKSOURCE_PATH, "r");
+       TEST_ASSERT(fp, "failed to open clocksource file, errno: %d", errno);
+
+       TEST_ASSERT(!fstat(fileno(fp), &st), "failed to stat clocksource file, errno: %d",
+                   errno);
+
+       clk_name = malloc(st.st_size);
+       TEST_ASSERT(clk_name, "failed to allocate buffer to read file");
+
+       TEST_ASSERT(fgets(clk_name, st.st_size, fp), "failed to read clocksource file: %d",
+                   ferror(fp));
+
+       fclose(fp);
+
+       return clk_name;
+}
index 271f6389158122a973fa597d68ee147f7169374c..f4eef6eb2dc2cc2bdefc90cbe5ac845be3a18b53 100644 (file)
@@ -69,7 +69,7 @@ static void *uffd_handler_thread_fn(void *arg)
                if (pollfd[1].revents & POLLIN) {
                        r = read(pollfd[1].fd, &tmp_chr, 1);
                        TEST_ASSERT(r == 1,
-                                   "Error reading pipefd in UFFD thread\n");
+                                   "Error reading pipefd in UFFD thread");
                        break;
                }
 
index d8288374078e4b3ce888bed569c7e59192d43e7c..f639b3e062e3a328165bfb6ed32f606cf1f48e76 100644 (file)
@@ -170,10 +170,10 @@ static uint64_t *virt_create_upper_pte(struct kvm_vm *vm,
                 * this level.
                 */
                TEST_ASSERT(current_level != target_level,
-                           "Cannot create hugepage at level: %u, vaddr: 0x%lx\n",
+                           "Cannot create hugepage at level: %u, vaddr: 0x%lx",
                            current_level, vaddr);
                TEST_ASSERT(!(*pte & PTE_LARGE_MASK),
-                           "Cannot create page table at level: %u, vaddr: 0x%lx\n",
+                           "Cannot create page table at level: %u, vaddr: 0x%lx",
                            current_level, vaddr);
        }
        return pte;
@@ -220,7 +220,7 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level)
        /* Fill in page table entry. */
        pte = virt_get_pte(vm, pde, vaddr, PG_LEVEL_4K);
        TEST_ASSERT(!(*pte & PTE_PRESENT_MASK),
-                   "PTE already present for 4k page at vaddr: 0x%lx\n", vaddr);
+                   "PTE already present for 4k page at vaddr: 0x%lx", vaddr);
        *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK | (paddr & PHYSICAL_PAGE_MASK);
 }
 
@@ -253,7 +253,7 @@ static bool vm_is_target_pte(uint64_t *pte, int *level, int current_level)
        if (*pte & PTE_LARGE_MASK) {
                TEST_ASSERT(*level == PG_LEVEL_NONE ||
                            *level == current_level,
-                           "Unexpected hugepage at level %d\n", current_level);
+                           "Unexpected hugepage at level %d", current_level);
                *level = current_level;
        }
 
@@ -825,7 +825,7 @@ void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
        struct kvm_regs regs;
 
        TEST_ASSERT(num >= 1 && num <= 6, "Unsupported number of args,\n"
-                   "  num: %u\n",
+                   "  num: %u",
                    num);
 
        va_start(ap, num);
@@ -1299,3 +1299,14 @@ void kvm_selftest_arch_init(void)
        host_cpu_is_intel = this_cpu_is_intel();
        host_cpu_is_amd = this_cpu_is_amd();
 }
+
+bool sys_clocksource_is_based_on_tsc(void)
+{
+       char *clk_name = sys_get_cur_clocksource();
+       bool ret = !strcmp(clk_name, "tsc\n") ||
+                  !strcmp(clk_name, "hyperv_clocksource_tsc_page\n");
+
+       free(clk_name);
+
+       return ret;
+}
index 59d97531c9b17f7b0c1893d1aa5a63575e3fdb5c..089b8925b6b22d9929bee551435ebdca0fa24764 100644 (file)
@@ -54,7 +54,7 @@ int vcpu_enable_evmcs(struct kvm_vcpu *vcpu)
        /* KVM should return supported EVMCS version range */
        TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
                    (evmcs_ver & 0xff) > 0,
-                   "Incorrect EVMCS version range: %x:%x\n",
+                   "Incorrect EVMCS version range: %x:%x",
                    evmcs_ver & 0xff, evmcs_ver >> 8);
 
        return evmcs_ver;
@@ -387,10 +387,10 @@ static void nested_create_pte(struct kvm_vm *vm,
                 * this level.
                 */
                TEST_ASSERT(current_level != target_level,
-                           "Cannot create hugepage at level: %u, nested_paddr: 0x%lx\n",
+                           "Cannot create hugepage at level: %u, nested_paddr: 0x%lx",
                            current_level, nested_paddr);
                TEST_ASSERT(!pte->page_size,
-                           "Cannot create page table at level: %u, nested_paddr: 0x%lx\n",
+                           "Cannot create page table at level: %u, nested_paddr: 0x%lx",
                            current_level, nested_paddr);
        }
 }
index 9855c41ca811fa69a77f41f212ddc6086d47467c..1563619666123fed1da83a2786d309c51cde25d3 100644 (file)
@@ -45,7 +45,7 @@ static void vcpu_worker(struct memstress_vcpu_args *vcpu_args)
        /* Let the guest access its memory until a stop signal is received */
        while (!READ_ONCE(memstress_args.stop_vcpus)) {
                ret = _vcpu_run(vcpu);
-               TEST_ASSERT(ret == 0, "vcpu_run failed: %d\n", ret);
+               TEST_ASSERT(ret == 0, "vcpu_run failed: %d", ret);
 
                if (get_ucall(vcpu, NULL) == UCALL_SYNC)
                        continue;
index 8698d1ab60d00f72399571b62b49314f3a8c401f..579a64f97333b8d0ebd4533fdfdee1a172ef731a 100644 (file)
@@ -175,11 +175,11 @@ static void wait_for_vcpu(void)
        struct timespec ts;
 
        TEST_ASSERT(!clock_gettime(CLOCK_REALTIME, &ts),
-                   "clock_gettime() failed: %d\n", errno);
+                   "clock_gettime() failed: %d", errno);
 
        ts.tv_sec += 2;
        TEST_ASSERT(!sem_timedwait(&vcpu_ready, &ts),
-                   "sem_timedwait() failed: %d\n", errno);
+                   "sem_timedwait() failed: %d", errno);
 }
 
 static void *vm_gpa2hva(struct vm_data *data, uint64_t gpa, uint64_t *rempages)
@@ -336,7 +336,7 @@ static bool prepare_vm(struct vm_data *data, int nslots, uint64_t *maxslots,
 
                gpa = vm_phy_pages_alloc(data->vm, npages, guest_addr, slot);
                TEST_ASSERT(gpa == guest_addr,
-                           "vm_phy_pages_alloc() failed\n");
+                           "vm_phy_pages_alloc() failed");
 
                data->hva_slots[slot - 1] = addr_gpa2hva(data->vm, guest_addr);
                memset(data->hva_slots[slot - 1], 0, npages * guest_page_size);
index 6652108816db462160230a17c4da32fa078526dc..6435e7a6564252fae5e1cbd2275a6fc0c3a7f12f 100644 (file)
@@ -49,15 +49,42 @@ bool filter_reg(__u64 reg)
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVPBMT:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBA:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBB:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBC:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBKB:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBKC:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBKX:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBS:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZFA:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZFH:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZFHMIN:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICBOM:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICBOZ:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICNTR:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICOND:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICSR:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZIFENCEI:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZIHINTNTL:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZIHINTPAUSE:
        case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZIHPM:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKND:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKNE:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKNH:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKR:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKSED:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKSH:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKT:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVBB:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVBC:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVFH:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVFHMIN:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKB:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKG:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKNED:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKNHA:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKNHB:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKSED:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKSH:
+       case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKT:
        /*
         * Like ISA_EXT registers, SBI_EXT registers are only visible when the
         * host supports them and disabling them does not affect the visibility
@@ -150,7 +177,7 @@ void finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c)
 
                /* Double check whether the desired extension was enabled */
                __TEST_REQUIRE(vcpu_has_ext(vcpu, feature),
-                              "%s not available, skipping tests\n", s->name);
+                              "%s not available, skipping tests", s->name);
        }
 }
 
@@ -394,15 +421,42 @@ static const char *isa_ext_single_id_to_str(__u64 reg_off)
                KVM_ISA_EXT_ARR(SVPBMT),
                KVM_ISA_EXT_ARR(ZBA),
                KVM_ISA_EXT_ARR(ZBB),
+               KVM_ISA_EXT_ARR(ZBC),
+               KVM_ISA_EXT_ARR(ZBKB),
+               KVM_ISA_EXT_ARR(ZBKC),
+               KVM_ISA_EXT_ARR(ZBKX),
                KVM_ISA_EXT_ARR(ZBS),
+               KVM_ISA_EXT_ARR(ZFA),
+               KVM_ISA_EXT_ARR(ZFH),
+               KVM_ISA_EXT_ARR(ZFHMIN),
                KVM_ISA_EXT_ARR(ZICBOM),
                KVM_ISA_EXT_ARR(ZICBOZ),
                KVM_ISA_EXT_ARR(ZICNTR),
                KVM_ISA_EXT_ARR(ZICOND),
                KVM_ISA_EXT_ARR(ZICSR),
                KVM_ISA_EXT_ARR(ZIFENCEI),
+               KVM_ISA_EXT_ARR(ZIHINTNTL),
                KVM_ISA_EXT_ARR(ZIHINTPAUSE),
                KVM_ISA_EXT_ARR(ZIHPM),
+               KVM_ISA_EXT_ARR(ZKND),
+               KVM_ISA_EXT_ARR(ZKNE),
+               KVM_ISA_EXT_ARR(ZKNH),
+               KVM_ISA_EXT_ARR(ZKR),
+               KVM_ISA_EXT_ARR(ZKSED),
+               KVM_ISA_EXT_ARR(ZKSH),
+               KVM_ISA_EXT_ARR(ZKT),
+               KVM_ISA_EXT_ARR(ZVBB),
+               KVM_ISA_EXT_ARR(ZVBC),
+               KVM_ISA_EXT_ARR(ZVFH),
+               KVM_ISA_EXT_ARR(ZVFHMIN),
+               KVM_ISA_EXT_ARR(ZVKB),
+               KVM_ISA_EXT_ARR(ZVKG),
+               KVM_ISA_EXT_ARR(ZVKNED),
+               KVM_ISA_EXT_ARR(ZVKNHA),
+               KVM_ISA_EXT_ARR(ZVKNHB),
+               KVM_ISA_EXT_ARR(ZVKSED),
+               KVM_ISA_EXT_ARR(ZVKSH),
+               KVM_ISA_EXT_ARR(ZVKT),
        };
 
        if (reg_off >= ARRAY_SIZE(kvm_isa_ext_reg_name))
@@ -888,15 +942,42 @@ KVM_ISA_EXT_SIMPLE_CONFIG(svnapot, SVNAPOT);
 KVM_ISA_EXT_SIMPLE_CONFIG(svpbmt, SVPBMT);
 KVM_ISA_EXT_SIMPLE_CONFIG(zba, ZBA);
 KVM_ISA_EXT_SIMPLE_CONFIG(zbb, ZBB);
+KVM_ISA_EXT_SIMPLE_CONFIG(zbc, ZBC);
+KVM_ISA_EXT_SIMPLE_CONFIG(zbkb, ZBKB);
+KVM_ISA_EXT_SIMPLE_CONFIG(zbkc, ZBKC);
+KVM_ISA_EXT_SIMPLE_CONFIG(zbkx, ZBKX);
 KVM_ISA_EXT_SIMPLE_CONFIG(zbs, ZBS);
+KVM_ISA_EXT_SIMPLE_CONFIG(zfa, ZFA);
+KVM_ISA_EXT_SIMPLE_CONFIG(zfh, ZFH);
+KVM_ISA_EXT_SIMPLE_CONFIG(zfhmin, ZFHMIN);
 KVM_ISA_EXT_SUBLIST_CONFIG(zicbom, ZICBOM);
 KVM_ISA_EXT_SUBLIST_CONFIG(zicboz, ZICBOZ);
 KVM_ISA_EXT_SIMPLE_CONFIG(zicntr, ZICNTR);
 KVM_ISA_EXT_SIMPLE_CONFIG(zicond, ZICOND);
 KVM_ISA_EXT_SIMPLE_CONFIG(zicsr, ZICSR);
 KVM_ISA_EXT_SIMPLE_CONFIG(zifencei, ZIFENCEI);
+KVM_ISA_EXT_SIMPLE_CONFIG(zihintntl, ZIHINTNTL);
 KVM_ISA_EXT_SIMPLE_CONFIG(zihintpause, ZIHINTPAUSE);
 KVM_ISA_EXT_SIMPLE_CONFIG(zihpm, ZIHPM);
+KVM_ISA_EXT_SIMPLE_CONFIG(zknd, ZKND);
+KVM_ISA_EXT_SIMPLE_CONFIG(zkne, ZKNE);
+KVM_ISA_EXT_SIMPLE_CONFIG(zknh, ZKNH);
+KVM_ISA_EXT_SIMPLE_CONFIG(zkr, ZKR);
+KVM_ISA_EXT_SIMPLE_CONFIG(zksed, ZKSED);
+KVM_ISA_EXT_SIMPLE_CONFIG(zksh, ZKSH);
+KVM_ISA_EXT_SIMPLE_CONFIG(zkt, ZKT);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvbb, ZVBB);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvbc, ZVBC);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvfh, ZVFH);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvfhmin, ZVFHMIN);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvkb, ZVKB);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvkg, ZVKG);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvkned, ZVKNED);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvknha, ZVKNHA);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvknhb, ZVKNHB);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvksed, ZVKSED);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvksh, ZVKSH);
+KVM_ISA_EXT_SIMPLE_CONFIG(zvkt, ZVKT);
 
 struct vcpu_reg_list *vcpu_configs[] = {
        &config_sbi_base,
@@ -914,14 +995,41 @@ struct vcpu_reg_list *vcpu_configs[] = {
        &config_svpbmt,
        &config_zba,
        &config_zbb,
+       &config_zbc,
+       &config_zbkb,
+       &config_zbkc,
+       &config_zbkx,
        &config_zbs,
+       &config_zfa,
+       &config_zfh,
+       &config_zfhmin,
        &config_zicbom,
        &config_zicboz,
        &config_zicntr,
        &config_zicond,
        &config_zicsr,
        &config_zifencei,
+       &config_zihintntl,
        &config_zihintpause,
        &config_zihpm,
+       &config_zknd,
+       &config_zkne,
+       &config_zknh,
+       &config_zkr,
+       &config_zksed,
+       &config_zksh,
+       &config_zkt,
+       &config_zvbb,
+       &config_zvbc,
+       &config_zvfh,
+       &config_zvfhmin,
+       &config_zvkb,
+       &config_zvkg,
+       &config_zvkned,
+       &config_zvknha,
+       &config_zvknhb,
+       &config_zvksed,
+       &config_zvksh,
+       &config_zvkt,
 };
 int vcpu_configs_n = ARRAY_SIZE(vcpu_configs);
index f74e76d03b7e306667221ee9c5411bda2af417d5..28f97fb520441476c374dffc0bcf24bf6553a021 100644 (file)
@@ -245,7 +245,7 @@ int main(int argc, char *argv[])
                } while (snapshot != atomic_read(&seq_cnt));
 
                TEST_ASSERT(rseq_cpu == cpu,
-                           "rseq CPU = %d, sched CPU = %d\n", rseq_cpu, cpu);
+                           "rseq CPU = %d, sched CPU = %d", rseq_cpu, cpu);
        }
 
        /*
@@ -256,7 +256,7 @@ int main(int argc, char *argv[])
         * migrations given the 1us+ delay in the migration task.
         */
        TEST_ASSERT(i > (NR_TASK_MIGRATIONS / 2),
-                   "Only performed %d KVM_RUNs, task stalled too much?\n", i);
+                   "Only performed %d KVM_RUNs, task stalled too much?", i);
 
        pthread_join(migration_thread, NULL);
 
index e41e2cb8ffa9797c470fb061a34fb106b687a47d..357943f2bea87fff66384bcf381cf9100a5a3a6b 100644 (file)
@@ -78,7 +78,7 @@ static void assert_noirq(struct kvm_vcpu *vcpu)
         * (notably, the emergency call interrupt we have injected) should
         * be cleared by the resets, so this should be 0.
         */
-       TEST_ASSERT(irqs >= 0, "Could not fetch IRQs: errno %d\n", errno);
+       TEST_ASSERT(irqs >= 0, "Could not fetch IRQs: errno %d", errno);
        TEST_ASSERT(!irqs, "IRQ pending");
 }
 
@@ -199,7 +199,7 @@ static void inject_irq(struct kvm_vcpu *vcpu)
        irq->type = KVM_S390_INT_EMERGENCY;
        irq->u.emerg.code = vcpu->id;
        irqs = __vcpu_ioctl(vcpu, KVM_S390_SET_IRQ_STATE, &irq_state);
-       TEST_ASSERT(irqs >= 0, "Error injecting EMERGENCY IRQ errno %d\n", errno);
+       TEST_ASSERT(irqs >= 0, "Error injecting EMERGENCY IRQ errno %d", errno);
 }
 
 static struct kvm_vm *create_vm(struct kvm_vcpu **vcpu)
index 636a70ddac1ea36151cb57a0dfd74ddcca33de14..43fb25ddc3eca3a83ba14c1905972243c4bda793 100644 (file)
@@ -39,13 +39,13 @@ static void guest_code(void)
 #define REG_COMPARE(reg) \
        TEST_ASSERT(left->reg == right->reg, \
                    "Register " #reg \
-                   " values did not match: 0x%llx, 0x%llx\n", \
+                   " values did not match: 0x%llx, 0x%llx", \
                    left->reg, right->reg)
 
 #define REG_COMPARE32(reg) \
        TEST_ASSERT(left->reg == right->reg, \
                    "Register " #reg \
-                   " values did not match: 0x%x, 0x%x\n", \
+                   " values did not match: 0x%x, 0x%x", \
                    left->reg, right->reg)
 
 
@@ -82,14 +82,14 @@ void test_read_invalid(struct kvm_vcpu *vcpu)
        run->kvm_valid_regs = INVALID_SYNC_FIELD;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
+                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d",
                    rv);
        run->kvm_valid_regs = 0;
 
        run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
+                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d",
                    rv);
        run->kvm_valid_regs = 0;
 }
@@ -103,14 +103,14 @@ void test_set_invalid(struct kvm_vcpu *vcpu)
        run->kvm_dirty_regs = INVALID_SYNC_FIELD;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
+                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d",
                    rv);
        run->kvm_dirty_regs = 0;
 
        run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
+                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d",
                    rv);
        run->kvm_dirty_regs = 0;
 }
@@ -125,12 +125,12 @@ void test_req_and_verify_all_valid_regs(struct kvm_vcpu *vcpu)
        /* Request and verify all valid register sets. */
        run->kvm_valid_regs = TEST_SYNC_FIELDS;
        rv = _vcpu_run(vcpu);
-       TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
+       TEST_ASSERT(rv == 0, "vcpu_run failed: %d", rv);
        TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
        TEST_ASSERT(run->s390_sieic.icptcode == 4 &&
                    (run->s390_sieic.ipa >> 8) == 0x83 &&
                    (run->s390_sieic.ipb >> 16) == 0x501,
-                   "Unexpected interception code: ic=%u, ipa=0x%x, ipb=0x%x\n",
+                   "Unexpected interception code: ic=%u, ipa=0x%x, ipb=0x%x",
                    run->s390_sieic.icptcode, run->s390_sieic.ipa,
                    run->s390_sieic.ipb);
 
@@ -161,7 +161,7 @@ void test_set_and_verify_various_reg_values(struct kvm_vcpu *vcpu)
        }
 
        rv = _vcpu_run(vcpu);
-       TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
+       TEST_ASSERT(rv == 0, "vcpu_run failed: %d", rv);
        TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
        TEST_ASSERT(run->s.regs.gprs[11] == 0xBAD1DEA + 1,
                    "r11 sync regs value incorrect 0x%llx.",
@@ -193,7 +193,7 @@ void test_clear_kvm_dirty_regs_bits(struct kvm_vcpu *vcpu)
        run->s.regs.gprs[11] = 0xDEADBEEF;
        run->s.regs.diag318 = 0x4B1D;
        rv = _vcpu_run(vcpu);
-       TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
+       TEST_ASSERT(rv == 0, "vcpu_run failed: %d", rv);
        TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
        TEST_ASSERT(run->s.regs.gprs[11] != 0xDEADBEEF,
                    "r11 sync regs value incorrect 0x%llx.",
index 075b80dbe2370d2ff472685f4b02b4e1243d7123..40337f566eebb319d07f332d4eab1e0a6d0c287f 100644 (file)
@@ -98,11 +98,11 @@ static void wait_for_vcpu(void)
        struct timespec ts;
 
        TEST_ASSERT(!clock_gettime(CLOCK_REALTIME, &ts),
-                   "clock_gettime() failed: %d\n", errno);
+                   "clock_gettime() failed: %d", errno);
 
        ts.tv_sec += 2;
        TEST_ASSERT(!sem_timedwait(&vcpu_ready, &ts),
-                   "sem_timedwait() failed: %d\n", errno);
+                   "sem_timedwait() failed: %d", errno);
 
        /* Wait for the vCPU thread to reenter the guest. */
        usleep(100000);
@@ -302,7 +302,7 @@ static void test_delete_memory_region(void)
        if (run->exit_reason == KVM_EXIT_INTERNAL_ERROR)
                TEST_ASSERT(regs.rip >= final_rip_start &&
                            regs.rip < final_rip_end,
-                           "Bad rip, expected 0x%lx - 0x%lx, got 0x%llx\n",
+                           "Bad rip, expected 0x%lx - 0x%lx, got 0x%llx",
                            final_rip_start, final_rip_end, regs.rip);
 
        kvm_vm_free(vm);
index 7f5b330b6a1b182f7a5890d3f7b67b7d2535accc..513d421a9bff85a96e619f187310769de7e48490 100644 (file)
@@ -108,7 +108,7 @@ static void enter_guest(struct kvm_vcpu *vcpu)
                        handle_abort(&uc);
                        return;
                default:
-                       TEST_ASSERT(0, "unhandled ucall %ld\n",
+                       TEST_ASSERT(0, "unhandled ucall %ld",
                                    get_ucall(vcpu, &uc));
                }
        }
index 11329e5ff945eb1c383c7237ebc349712734dd50..eae521f050e09fd6f69e896c03cf381ac05c4d71 100644 (file)
@@ -221,7 +221,7 @@ int main(int argc, char *argv[])
        vm_vaddr_t amx_cfg, tiledata, xstate;
        struct ucall uc;
        u32 amx_offset;
-       int stage, ret;
+       int ret;
 
        /*
         * Note, all off-by-default features must be enabled before anything
@@ -263,7 +263,7 @@ int main(int argc, char *argv[])
        memset(addr_gva2hva(vm, xstate), 0, PAGE_SIZE * DIV_ROUND_UP(XSAVE_SIZE, PAGE_SIZE));
        vcpu_args_set(vcpu, 3, amx_cfg, tiledata, xstate);
 
-       for (stage = 1; ; stage++) {
+       for (;;) {
                vcpu_run(vcpu);
                TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
@@ -296,7 +296,7 @@ int main(int argc, char *argv[])
                                void *tiles_data = (void *)addr_gva2hva(vm, tiledata);
                                /* Only check TMM0 register, 1 tile */
                                ret = memcmp(amx_start, tiles_data, TILE_SIZE);
-                               TEST_ASSERT(ret == 0, "memcmp failed, ret=%d\n", ret);
+                               TEST_ASSERT(ret == 0, "memcmp failed, ret=%d", ret);
                                kvm_x86_state_cleanup(state);
                                break;
                        case 9:
index 3b34d8156d1c97a879d497a12eefe4f110628973..8c579ce714e9a7ce3982123b089856c3b5963d43 100644 (file)
@@ -84,7 +84,7 @@ static void compare_cpuids(const struct kvm_cpuid2 *cpuid1,
 
                TEST_ASSERT(e1->function == e2->function &&
                            e1->index == e2->index && e1->flags == e2->flags,
-                           "CPUID entries[%d] mismtach: 0x%x.%d.%x vs. 0x%x.%d.%x\n",
+                           "CPUID entries[%d] mismtach: 0x%x.%d.%x vs. 0x%x.%d.%x",
                            i, e1->function, e1->index, e1->flags,
                            e2->function, e2->index, e2->flags);
 
@@ -170,7 +170,7 @@ static void test_get_cpuid2(struct kvm_vcpu *vcpu)
 
        vcpu_ioctl(vcpu, KVM_GET_CPUID2, cpuid);
        TEST_ASSERT(cpuid->nent == vcpu->cpuid->nent,
-                   "KVM didn't update nent on success, wanted %u, got %u\n",
+                   "KVM didn't update nent on success, wanted %u, got %u",
                    vcpu->cpuid->nent, cpuid->nent);
 
        for (i = 0; i < vcpu->cpuid->nent; i++) {
index 634c6bfcd5720717e0d4cc93e9cdf92ae96fb1d0..ee3b384b991c8be2957bdcf56fa52aa6a4a00a26 100644 (file)
@@ -92,7 +92,6 @@ static void run_test(enum vm_guest_mode mode, void *unused)
        uint64_t host_num_pages;
        uint64_t pages_per_slot;
        int i;
-       uint64_t total_4k_pages;
        struct kvm_page_stats stats_populated;
        struct kvm_page_stats stats_dirty_logging_enabled;
        struct kvm_page_stats stats_dirty_pass[ITERATIONS];
@@ -107,6 +106,9 @@ static void run_test(enum vm_guest_mode mode, void *unused)
        guest_num_pages = vm_adjust_num_guest_pages(mode, guest_num_pages);
        host_num_pages = vm_num_host_pages(mode, guest_num_pages);
        pages_per_slot = host_num_pages / SLOTS;
+       TEST_ASSERT_EQ(host_num_pages, pages_per_slot * SLOTS);
+       TEST_ASSERT(!(host_num_pages % 512),
+                   "Number of pages, '%lu' not a multiple of 2MiB", host_num_pages);
 
        bitmaps = memstress_alloc_bitmaps(SLOTS, pages_per_slot);
 
@@ -165,10 +167,8 @@ static void run_test(enum vm_guest_mode mode, void *unused)
        memstress_free_bitmaps(bitmaps, SLOTS);
        memstress_destroy_vm(vm);
 
-       /* Make assertions about the page counts. */
-       total_4k_pages = stats_populated.pages_4k;
-       total_4k_pages += stats_populated.pages_2m * 512;
-       total_4k_pages += stats_populated.pages_1g * 512 * 512;
+       TEST_ASSERT_EQ((stats_populated.pages_2m * 512 +
+                       stats_populated.pages_1g * 512 * 512), host_num_pages);
 
        /*
         * Check that all huge pages were split. Since large pages can only
@@ -180,19 +180,22 @@ static void run_test(enum vm_guest_mode mode, void *unused)
         */
        if (dirty_log_manual_caps) {
                TEST_ASSERT_EQ(stats_clear_pass[0].hugepages, 0);
-               TEST_ASSERT_EQ(stats_clear_pass[0].pages_4k, total_4k_pages);
+               TEST_ASSERT(stats_clear_pass[0].pages_4k >= host_num_pages,
+                           "Expected at least '%lu' 4KiB pages, found only '%lu'",
+                           host_num_pages, stats_clear_pass[0].pages_4k);
                TEST_ASSERT_EQ(stats_dirty_logging_enabled.hugepages, stats_populated.hugepages);
        } else {
                TEST_ASSERT_EQ(stats_dirty_logging_enabled.hugepages, 0);
-               TEST_ASSERT_EQ(stats_dirty_logging_enabled.pages_4k, total_4k_pages);
+               TEST_ASSERT(stats_dirty_logging_enabled.pages_4k >= host_num_pages,
+                           "Expected at least '%lu' 4KiB pages, found only '%lu'",
+                           host_num_pages, stats_dirty_logging_enabled.pages_4k);
        }
 
        /*
         * Once dirty logging is disabled and the vCPUs have touched all their
-        * memory again, the page counts should be the same as they were
+        * memory again, the hugepage counts should be the same as they were
         * right after initial population of memory.
         */
-       TEST_ASSERT_EQ(stats_populated.pages_4k, stats_repopulated.pages_4k);
        TEST_ASSERT_EQ(stats_populated.pages_2m, stats_repopulated.pages_2m);
        TEST_ASSERT_EQ(stats_populated.pages_1g, stats_repopulated.pages_1g);
 }
index 0a1573d52882b7b127307a829b0d1dc4d1af6560..37b1a9f5286447a1bb4a8c8f7a69c807ac0d6ced 100644 (file)
@@ -41,7 +41,7 @@ static inline void handle_flds_emulation_failure_exit(struct kvm_vcpu *vcpu)
 
        insn_bytes = run->emulation_failure.insn_bytes;
        TEST_ASSERT(insn_bytes[0] == 0xd9 && insn_bytes[1] == 0,
-                   "Expected 'flds [eax]', opcode '0xd9 0x00', got opcode 0x%02x 0x%02x\n",
+                   "Expected 'flds [eax]', opcode '0xd9 0x00', got opcode 0x%02x 0x%02x",
                    insn_bytes[0], insn_bytes[1]);
 
        vcpu_regs_get(vcpu, &regs);
index f5e1e98f04f9ef0a00f3d80ba8a0bd94f90feffd..e058bc676cd6930d54593093579fff15e1930d91 100644 (file)
@@ -212,6 +212,7 @@ int main(void)
        int stage;
 
        TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_TIME));
+       TEST_REQUIRE(sys_clocksource_is_based_on_tsc());
 
        vm = vm_create_with_one_vcpu(&vcpu, guest_main);
 
@@ -220,7 +221,7 @@ int main(void)
        tsc_page_gva = vm_vaddr_alloc_page(vm);
        memset(addr_gva2hva(vm, tsc_page_gva), 0x0, getpagesize());
        TEST_ASSERT((addr_gva2gpa(vm, tsc_page_gva) & (getpagesize() - 1)) == 0,
-               "TSC page has to be page aligned\n");
+               "TSC page has to be page aligned");
        vcpu_args_set(vcpu, 2, tsc_page_gva, addr_gva2gpa(vm, tsc_page_gva));
 
        host_check_tsc_msr_rdtsc(vcpu);
@@ -237,7 +238,7 @@ int main(void)
                        break;
                case UCALL_DONE:
                        /* Keep in sync with guest_main() */
-                       TEST_ASSERT(stage == 11, "Testing ended prematurely, stage %d\n",
+                       TEST_ASSERT(stage == 11, "Testing ended prematurely, stage %d",
                                    stage);
                        goto out;
                default:
index 4f4193fc74ffa29454c193ed741603c5fef1004b..b923a285e96f9492108ac17c21a070a4dd4ffa61 100644 (file)
@@ -454,7 +454,7 @@ static void guest_test_msrs_access(void)
                case 44:
                        /* MSR is not available when CPUID feature bit is unset */
                        if (!has_invtsc)
-                               continue;
+                               goto next_stage;
                        msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
                        msr->write = false;
                        msr->fault_expected = true;
@@ -462,7 +462,7 @@ static void guest_test_msrs_access(void)
                case 45:
                        /* MSR is vailable when CPUID feature bit is set */
                        if (!has_invtsc)
-                               continue;
+                               goto next_stage;
                        vcpu_set_cpuid_feature(vcpu, HV_ACCESS_TSC_INVARIANT);
                        msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
                        msr->write = false;
@@ -471,7 +471,7 @@ static void guest_test_msrs_access(void)
                case 46:
                        /* Writing bits other than 0 is forbidden */
                        if (!has_invtsc)
-                               continue;
+                               goto next_stage;
                        msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
                        msr->write = true;
                        msr->write_val = 0xdeadbeef;
@@ -480,7 +480,7 @@ static void guest_test_msrs_access(void)
                case 47:
                        /* Setting bit 0 enables the feature */
                        if (!has_invtsc)
-                               continue;
+                               goto next_stage;
                        msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
                        msr->write = true;
                        msr->write_val = 1;
@@ -513,6 +513,7 @@ static void guest_test_msrs_access(void)
                        return;
                }
 
+next_stage:
                stage++;
                kvm_vm_free(vm);
        }
index 65e5f4c05068a8fff78caf386f76ef107ac407f2..f1617762c22fecaff954824c3ca09cebec1eb78d 100644 (file)
@@ -289,7 +289,7 @@ int main(int argc, char *argv[])
                switch (get_ucall(vcpu[0], &uc)) {
                case UCALL_SYNC:
                        TEST_ASSERT(uc.args[1] == stage,
-                                   "Unexpected stage: %ld (%d expected)\n",
+                                   "Unexpected stage: %ld (%d expected)",
                                    uc.args[1], stage);
                        break;
                case UCALL_DONE:
index c4443f71f8dd01f6aafde337c618d414c61c1ce3..05b56095cf76f6b8857f7f83bccdf68b3787d759 100644 (file)
@@ -658,7 +658,7 @@ int main(int argc, char *argv[])
                switch (get_ucall(vcpu[0], &uc)) {
                case UCALL_SYNC:
                        TEST_ASSERT(uc.args[1] == stage,
-                                   "Unexpected stage: %ld (%d expected)\n",
+                                   "Unexpected stage: %ld (%d expected)",
                                    uc.args[1], stage);
                        break;
                case UCALL_ABORT:
index 1778704360a6634ee7df3dfacd8f63fd3d236cab..5bc12222d87af696dc2f35e8874c4eb3f58a4f7e 100644 (file)
@@ -92,7 +92,7 @@ static void setup_clock(struct kvm_vm *vm, struct test_case *test_case)
                                break;
                } while (errno == EINTR);
 
-               TEST_ASSERT(!r, "clock_gettime() failed: %d\n", r);
+               TEST_ASSERT(!r, "clock_gettime() failed: %d", r);
 
                data.realtime = ts.tv_sec * NSEC_PER_SEC;
                data.realtime += ts.tv_nsec;
@@ -127,47 +127,11 @@ static void enter_guest(struct kvm_vcpu *vcpu)
                        handle_abort(&uc);
                        return;
                default:
-                       TEST_ASSERT(0, "unhandled ucall: %ld\n", uc.cmd);
+                       TEST_ASSERT(0, "unhandled ucall: %ld", uc.cmd);
                }
        }
 }
 
-#define CLOCKSOURCE_PATH "/sys/devices/system/clocksource/clocksource0/current_clocksource"
-
-static void check_clocksource(void)
-{
-       char *clk_name;
-       struct stat st;
-       FILE *fp;
-
-       fp = fopen(CLOCKSOURCE_PATH, "r");
-       if (!fp) {
-               pr_info("failed to open clocksource file: %d; assuming TSC.\n",
-                       errno);
-               return;
-       }
-
-       if (fstat(fileno(fp), &st)) {
-               pr_info("failed to stat clocksource file: %d; assuming TSC.\n",
-                       errno);
-               goto out;
-       }
-
-       clk_name = malloc(st.st_size);
-       TEST_ASSERT(clk_name, "failed to allocate buffer to read file\n");
-
-       if (!fgets(clk_name, st.st_size, fp)) {
-               pr_info("failed to read clocksource file: %d; assuming TSC.\n",
-                       ferror(fp));
-               goto out;
-       }
-
-       TEST_ASSERT(!strncmp(clk_name, "tsc\n", st.st_size),
-                   "clocksource not supported: %s", clk_name);
-out:
-       fclose(fp);
-}
-
 int main(void)
 {
        struct kvm_vcpu *vcpu;
@@ -179,7 +143,7 @@ int main(void)
        flags = kvm_check_cap(KVM_CAP_ADJUST_CLOCK);
        TEST_REQUIRE(flags & KVM_CLOCK_REALTIME);
 
-       check_clocksource();
+       TEST_REQUIRE(sys_clocksource_is_based_on_tsc());
 
        vm = vm_create_with_one_vcpu(&vcpu, guest_main);
 
index 83e25bccc139decff79249e99a336ef2cb8cc820..17bbb96fc4dfcbc25e2ed62e5010d2d71a9d1746 100644 (file)
@@ -257,9 +257,9 @@ int main(int argc, char **argv)
        TEST_REQUIRE(kvm_has_cap(KVM_CAP_VM_DISABLE_NX_HUGE_PAGES));
 
        __TEST_REQUIRE(token == MAGIC_TOKEN,
-                      "This test must be run with the magic token %d.\n"
-                      "This is done by nx_huge_pages_test.sh, which\n"
-                      "also handles environment setup for the test.", MAGIC_TOKEN);
+                      "This test must be run with the magic token via '-t %d'.\n"
+                      "Running via nx_huge_pages_test.sh, which also handles "
+                      "environment setup, is strongly recommended.", MAGIC_TOKEN);
 
        run_test(reclaim_period_ms, false, reboot_permissions);
        run_test(reclaim_period_ms, true, reboot_permissions);
index c9a07963d68aaedcc6b45d4e00e932e5981645b0..87011965dc41664d46bb285fa5dd408876fe20c2 100644 (file)
@@ -44,7 +44,7 @@ static void test_msr_platform_info_enabled(struct kvm_vcpu *vcpu)
 
        get_ucall(vcpu, &uc);
        TEST_ASSERT(uc.cmd == UCALL_SYNC,
-                       "Received ucall other than UCALL_SYNC: %lu\n", uc.cmd);
+                       "Received ucall other than UCALL_SYNC: %lu", uc.cmd);
        TEST_ASSERT((uc.args[1] & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) ==
                MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
                "Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.",
index 283cc55597a4fe28c02197ea18c269b9294a16b2..a3bd54b925abaf10331886385f983001c47ebb06 100644 (file)
@@ -866,7 +866,7 @@ static void __test_fixed_counter_bitmap(struct kvm_vcpu *vcpu, uint8_t idx,
         * userspace doesn't set any pmu filter.
         */
        count = run_vcpu_to_sync(vcpu);
-       TEST_ASSERT(count, "Unexpected count value: %ld\n", count);
+       TEST_ASSERT(count, "Unexpected count value: %ld", count);
 
        for (i = 0; i < BIT(nr_fixed_counters); i++) {
                bitmap = BIT(i);
index c7ef97561038e8bc297324387160990f170f53a9..a49828adf2949464b668f530a977e9efd9d75888 100644 (file)
@@ -91,7 +91,7 @@ static void sev_migrate_from(struct kvm_vm *dst, struct kvm_vm *src)
        int ret;
 
        ret = __sev_migrate_from(dst, src);
-       TEST_ASSERT(!ret, "Migration failed, ret: %d, errno: %d\n", ret, errno);
+       TEST_ASSERT(!ret, "Migration failed, ret: %d, errno: %d", ret, errno);
 }
 
 static void test_sev_migrate_from(bool es)
@@ -113,7 +113,7 @@ static void test_sev_migrate_from(bool es)
        /* Migrate the guest back to the original VM. */
        ret = __sev_migrate_from(src_vm, dst_vms[NR_MIGRATE_TEST_VMS - 1]);
        TEST_ASSERT(ret == -1 && errno == EIO,
-                   "VM that was migrated from should be dead. ret %d, errno: %d\n", ret,
+                   "VM that was migrated from should be dead. ret %d, errno: %d", ret,
                    errno);
 
        kvm_vm_free(src_vm);
@@ -172,7 +172,7 @@ static void test_sev_migrate_parameters(void)
        vm_no_sev = aux_vm_create(true);
        ret = __sev_migrate_from(vm_no_vcpu, vm_no_sev);
        TEST_ASSERT(ret == -1 && errno == EINVAL,
-                   "Migrations require SEV enabled. ret %d, errno: %d\n", ret,
+                   "Migrations require SEV enabled. ret %d, errno: %d", ret,
                    errno);
 
        if (!have_sev_es)
@@ -187,25 +187,25 @@ static void test_sev_migrate_parameters(void)
        ret = __sev_migrate_from(sev_vm, sev_es_vm);
        TEST_ASSERT(
                ret == -1 && errno == EINVAL,
-               "Should not be able migrate to SEV enabled VM. ret: %d, errno: %d\n",
+               "Should not be able migrate to SEV enabled VM. ret: %d, errno: %d",
                ret, errno);
 
        ret = __sev_migrate_from(sev_es_vm, sev_vm);
        TEST_ASSERT(
                ret == -1 && errno == EINVAL,
-               "Should not be able migrate to SEV-ES enabled VM. ret: %d, errno: %d\n",
+               "Should not be able migrate to SEV-ES enabled VM. ret: %d, errno: %d",
                ret, errno);
 
        ret = __sev_migrate_from(vm_no_vcpu, sev_es_vm);
        TEST_ASSERT(
                ret == -1 && errno == EINVAL,
-               "SEV-ES migrations require same number of vCPUS. ret: %d, errno: %d\n",
+               "SEV-ES migrations require same number of vCPUS. ret: %d, errno: %d",
                ret, errno);
 
        ret = __sev_migrate_from(vm_no_vcpu, sev_es_vm_no_vmsa);
        TEST_ASSERT(
                ret == -1 && errno == EINVAL,
-               "SEV-ES migrations require UPDATE_VMSA. ret %d, errno: %d\n",
+               "SEV-ES migrations require UPDATE_VMSA. ret %d, errno: %d",
                ret, errno);
 
        kvm_vm_free(sev_vm);
@@ -227,7 +227,7 @@ static void sev_mirror_create(struct kvm_vm *dst, struct kvm_vm *src)
        int ret;
 
        ret = __sev_mirror_create(dst, src);
-       TEST_ASSERT(!ret, "Copying context failed, ret: %d, errno: %d\n", ret, errno);
+       TEST_ASSERT(!ret, "Copying context failed, ret: %d, errno: %d", ret, errno);
 }
 
 static void verify_mirror_allowed_cmds(int vm_fd)
@@ -259,7 +259,7 @@ static void verify_mirror_allowed_cmds(int vm_fd)
                ret = __sev_ioctl(vm_fd, cmd_id, NULL, &fw_error);
                TEST_ASSERT(
                        ret == -1 && errno == EINVAL,
-                       "Should not be able call command: %d. ret: %d, errno: %d\n",
+                       "Should not be able call command: %d. ret: %d, errno: %d",
                        cmd_id, ret, errno);
        }
 
@@ -301,18 +301,18 @@ static void test_sev_mirror_parameters(void)
        ret = __sev_mirror_create(sev_vm, sev_vm);
        TEST_ASSERT(
                ret == -1 && errno == EINVAL,
-               "Should not be able copy context to self. ret: %d, errno: %d\n",
+               "Should not be able copy context to self. ret: %d, errno: %d",
                ret, errno);
 
        ret = __sev_mirror_create(vm_no_vcpu, vm_with_vcpu);
        TEST_ASSERT(ret == -1 && errno == EINVAL,
-                   "Copy context requires SEV enabled. ret %d, errno: %d\n", ret,
+                   "Copy context requires SEV enabled. ret %d, errno: %d", ret,
                    errno);
 
        ret = __sev_mirror_create(vm_with_vcpu, sev_vm);
        TEST_ASSERT(
                ret == -1 && errno == EINVAL,
-               "SEV copy context requires no vCPUS on the destination. ret: %d, errno: %d\n",
+               "SEV copy context requires no vCPUS on the destination. ret: %d, errno: %d",
                ret, errno);
 
        if (!have_sev_es)
@@ -322,13 +322,13 @@ static void test_sev_mirror_parameters(void)
        ret = __sev_mirror_create(sev_vm, sev_es_vm);
        TEST_ASSERT(
                ret == -1 && errno == EINVAL,
-               "Should not be able copy context to SEV enabled VM. ret: %d, errno: %d\n",
+               "Should not be able copy context to SEV enabled VM. ret: %d, errno: %d",
                ret, errno);
 
        ret = __sev_mirror_create(sev_es_vm, sev_vm);
        TEST_ASSERT(
                ret == -1 && errno == EINVAL,
-               "Should not be able copy context to SEV-ES enabled VM. ret: %d, errno: %d\n",
+               "Should not be able copy context to SEV-ES enabled VM. ret: %d, errno: %d",
                ret, errno);
 
        kvm_vm_free(sev_es_vm);
index 06edf00a97d61dc3ca265926c2043d839daddeeb..1a46dd7bb39136e51b1e021be08667b84c2fe001 100644 (file)
@@ -74,7 +74,7 @@ int main(int argc, char *argv[])
                                    MEM_REGION_SIZE / PAGE_SIZE, 0);
        gpa = vm_phy_pages_alloc(vm, MEM_REGION_SIZE / PAGE_SIZE,
                                 MEM_REGION_GPA, MEM_REGION_SLOT);
-       TEST_ASSERT(gpa == MEM_REGION_GPA, "Failed vm_phy_pages_alloc\n");
+       TEST_ASSERT(gpa == MEM_REGION_GPA, "Failed vm_phy_pages_alloc");
        virt_map(vm, MEM_REGION_GVA, MEM_REGION_GPA, 1);
        hva = addr_gpa2hva(vm, MEM_REGION_GPA);
        memset(hva, 0, PAGE_SIZE);
@@ -102,7 +102,7 @@ int main(int argc, char *argv[])
        case UCALL_DONE:
                break;
        default:
-               TEST_FAIL("Unrecognized ucall: %lu\n", uc.cmd);
+               TEST_FAIL("Unrecognized ucall: %lu", uc.cmd);
        }
 
        kvm_vm_free(vm);
index 00965ba33f730c2a443773dc89e41d465c39beeb..a91b5b145fa35ac81dfaa225ff350e4186a229d0 100644 (file)
@@ -46,7 +46,7 @@ static void compare_regs(struct kvm_regs *left, struct kvm_regs *right)
 #define REG_COMPARE(reg) \
        TEST_ASSERT(left->reg == right->reg, \
                    "Register " #reg \
-                   " values did not match: 0x%llx, 0x%llx\n", \
+                   " values did not match: 0x%llx, 0x%llx", \
                    left->reg, right->reg)
        REG_COMPARE(rax);
        REG_COMPARE(rbx);
@@ -230,14 +230,14 @@ int main(int argc, char *argv[])
        run->kvm_valid_regs = INVALID_SYNC_FIELD;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
+                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d",
                    rv);
        run->kvm_valid_regs = 0;
 
        run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
+                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d",
                    rv);
        run->kvm_valid_regs = 0;
 
@@ -245,14 +245,14 @@ int main(int argc, char *argv[])
        run->kvm_dirty_regs = INVALID_SYNC_FIELD;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
+                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d",
                    rv);
        run->kvm_dirty_regs = 0;
 
        run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
+                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d",
                    rv);
        run->kvm_dirty_regs = 0;
 
index 0ed32ec903d03548ce11fa5bcc42eba329808506..dcbb3c29fb8e9f82b9dce0b222111f8a8eb4776a 100644 (file)
@@ -143,7 +143,7 @@ static void run_vcpu_expect_gp(struct kvm_vcpu *vcpu)
 
        TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
        TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_SYNC,
-                   "Expect UCALL_SYNC\n");
+                   "Expect UCALL_SYNC");
        TEST_ASSERT(uc.args[1] == SYNC_GP, "#GP is expected.");
        printf("vCPU received GP in guest.\n");
 }
@@ -188,7 +188,7 @@ static void *run_ucna_injection(void *arg)
 
        TEST_ASSERT_KVM_EXIT_REASON(params->vcpu, KVM_EXIT_IO);
        TEST_ASSERT(get_ucall(params->vcpu, &uc) == UCALL_SYNC,
-                   "Expect UCALL_SYNC\n");
+                   "Expect UCALL_SYNC");
        TEST_ASSERT(uc.args[1] == SYNC_FIRST_UCNA, "Injecting first UCNA.");
 
        printf("Injecting first UCNA at %#x.\n", FIRST_UCNA_ADDR);
@@ -198,7 +198,7 @@ static void *run_ucna_injection(void *arg)
 
        TEST_ASSERT_KVM_EXIT_REASON(params->vcpu, KVM_EXIT_IO);
        TEST_ASSERT(get_ucall(params->vcpu, &uc) == UCALL_SYNC,
-                   "Expect UCALL_SYNC\n");
+                   "Expect UCALL_SYNC");
        TEST_ASSERT(uc.args[1] == SYNC_SECOND_UCNA, "Injecting second UCNA.");
 
        printf("Injecting second UCNA at %#x.\n", SECOND_UCNA_ADDR);
@@ -208,7 +208,7 @@ static void *run_ucna_injection(void *arg)
 
        TEST_ASSERT_KVM_EXIT_REASON(params->vcpu, KVM_EXIT_IO);
        if (get_ucall(params->vcpu, &uc) == UCALL_ABORT) {
-               TEST_ASSERT(false, "vCPU assertion failure: %s.\n",
+               TEST_ASSERT(false, "vCPU assertion failure: %s.",
                            (const char *)uc.args[0]);
        }
 
index 255c50b0dc32675dfef64e65e1a0c6b164d0ca39..9481cbcf284f69b662a2f9f1a5fb3ff304ab0605 100644 (file)
@@ -71,7 +71,7 @@ int main(int argc, char *argv[])
                        break;
 
                TEST_ASSERT(run->io.port == 0x80,
-                           "Expected I/O at port 0x80, got port 0x%x\n", run->io.port);
+                           "Expected I/O at port 0x80, got port 0x%x", run->io.port);
 
                /*
                 * Modify the rep string count in RCX: 2 => 1 and 3 => 8192.
index 2bed5fb3a0d6e51aa63f9732d77dac330378d2c8..a81a24761aac072a0359305826712a917ed06bba 100644 (file)
@@ -99,7 +99,7 @@ int main(int argc, char *argv[])
                        TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR);
                        TEST_ASSERT(run->internal.suberror ==
                                    KVM_INTERNAL_ERROR_EMULATION,
-                                   "Got internal suberror other than KVM_INTERNAL_ERROR_EMULATION: %u\n",
+                                   "Got internal suberror other than KVM_INTERNAL_ERROR_EMULATION: %u",
                                    run->internal.suberror);
                        break;
                }
index e4ad5fef52ffc5b08ec8d3f445b518b52229e672..7f6f5f23fb9b67fcb186a0e9c9ad00aaced6d2d3 100644 (file)
@@ -128,17 +128,17 @@ int main(int argc, char *argv[])
                         */
                        kvm_vm_get_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap);
                        if (uc.args[1]) {
-                               TEST_ASSERT(test_bit(0, bmap), "Page 0 incorrectly reported clean\n");
-                               TEST_ASSERT(host_test_mem[0] == 1, "Page 0 not written by guest\n");
+                               TEST_ASSERT(test_bit(0, bmap), "Page 0 incorrectly reported clean");
+                               TEST_ASSERT(host_test_mem[0] == 1, "Page 0 not written by guest");
                        } else {
-                               TEST_ASSERT(!test_bit(0, bmap), "Page 0 incorrectly reported dirty\n");
-                               TEST_ASSERT(host_test_mem[0] == 0xaaaaaaaaaaaaaaaaULL, "Page 0 written by guest\n");
+                               TEST_ASSERT(!test_bit(0, bmap), "Page 0 incorrectly reported dirty");
+                               TEST_ASSERT(host_test_mem[0] == 0xaaaaaaaaaaaaaaaaULL, "Page 0 written by guest");
                        }
 
-                       TEST_ASSERT(!test_bit(1, bmap), "Page 1 incorrectly reported dirty\n");
-                       TEST_ASSERT(host_test_mem[4096 / 8] == 0xaaaaaaaaaaaaaaaaULL, "Page 1 written by guest\n");
-                       TEST_ASSERT(!test_bit(2, bmap), "Page 2 incorrectly reported dirty\n");
-                       TEST_ASSERT(host_test_mem[8192 / 8] == 0xaaaaaaaaaaaaaaaaULL, "Page 2 written by guest\n");
+                       TEST_ASSERT(!test_bit(1, bmap), "Page 1 incorrectly reported dirty");
+                       TEST_ASSERT(host_test_mem[4096 / 8] == 0xaaaaaaaaaaaaaaaaULL, "Page 1 written by guest");
+                       TEST_ASSERT(!test_bit(2, bmap), "Page 2 incorrectly reported dirty");
+                       TEST_ASSERT(host_test_mem[8192 / 8] == 0xaaaaaaaaaaaaaaaaULL, "Page 2 written by guest");
                        break;
                case UCALL_DONE:
                        done = true;
index a9b827c69f32c5f96548d040c72d979166041f19..fad3634fd9eb62e34ded1c3f59b1d38a0b61d03a 100644 (file)
@@ -28,7 +28,7 @@ static void __run_vcpu_with_invalid_state(struct kvm_vcpu *vcpu)
 
        TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR);
        TEST_ASSERT(run->emulation_failure.suberror == KVM_INTERNAL_ERROR_EMULATION,
-                   "Expected emulation failure, got %d\n",
+                   "Expected emulation failure, got %d",
                    run->emulation_failure.suberror);
 }
 
index e710b6e7fb384aac124ad0c7f646a872b347ad51..1759fa5cb3f29c337a09a5d15569ff028067e2db 100644 (file)
@@ -116,23 +116,6 @@ static void l1_guest_code(struct vmx_pages *vmx_pages)
        GUEST_DONE();
 }
 
-static bool system_has_stable_tsc(void)
-{
-       bool tsc_is_stable;
-       FILE *fp;
-       char buf[4];
-
-       fp = fopen("/sys/devices/system/clocksource/clocksource0/current_clocksource", "r");
-       if (fp == NULL)
-               return false;
-
-       tsc_is_stable = fgets(buf, sizeof(buf), fp) &&
-                       !strncmp(buf, "tsc", sizeof(buf));
-
-       fclose(fp);
-       return tsc_is_stable;
-}
-
 int main(int argc, char *argv[])
 {
        struct kvm_vcpu *vcpu;
@@ -148,7 +131,7 @@ int main(int argc, char *argv[])
 
        TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
        TEST_REQUIRE(kvm_has_cap(KVM_CAP_TSC_CONTROL));
-       TEST_REQUIRE(system_has_stable_tsc());
+       TEST_REQUIRE(sys_clocksource_is_based_on_tsc());
 
        /*
         * We set L1's scale factor to be a random number from 2 to 10.
index 67ac2a3292efd4e5a4ff24073af25849ce375dd9..725c206ba0b92bc9d073dcbc7d8403cb7d2f0bd1 100644 (file)
@@ -216,7 +216,7 @@ static void *vcpu_thread(void *arg)
                            "Halting vCPU halted %lu times, woke %lu times, received %lu IPIs.\n"
                            "Halter TPR=%#x PPR=%#x LVR=%#x\n"
                            "Migrations attempted: %lu\n"
-                           "Migrations completed: %lu\n",
+                           "Migrations completed: %lu",
                            vcpu->id, (const char *)uc.args[0],
                            params->data->ipis_sent, params->data->hlt_count,
                            params->data->wake_count,
@@ -288,7 +288,7 @@ void do_migrations(struct test_data_page *data, int run_secs, int delay_usecs,
        }
 
        TEST_ASSERT(nodes > 1,
-                   "Did not find at least 2 numa nodes. Can't do migration\n");
+                   "Did not find at least 2 numa nodes. Can't do migration");
 
        fprintf(stderr, "Migrating amongst %d nodes found\n", nodes);
 
@@ -347,7 +347,7 @@ void do_migrations(struct test_data_page *data, int run_secs, int delay_usecs,
                                    wake_count != data->wake_count,
                                    "IPI, HLT and wake count have not increased "
                                    "in the last %lu seconds. "
-                                   "HLTer is likely hung.\n", interval_secs);
+                                   "HLTer is likely hung.", interval_secs);
 
                        ipis_sent = data->ipis_sent;
                        hlt_count = data->hlt_count;
@@ -381,7 +381,7 @@ void get_cmdline_args(int argc, char *argv[], int *run_secs,
                                    "-m adds calls to migrate_pages while vCPUs are running."
                                    " Default is no migrations.\n"
                                    "-d <delay microseconds> - delay between migrate_pages() calls."
-                                   " Default is %d microseconds.\n",
+                                   " Default is %d microseconds.",
                                    DEFAULT_RUN_SECS, DEFAULT_DELAY_USECS);
                }
        }
index dc6217440db3ae193fd9bfbcfbaadea223e57c03..25a0b0db5c3c9dfac6819de37e8c7d0a541935fb 100644 (file)
@@ -116,7 +116,7 @@ int main(int argc, char *argv[])
                vcpu_run(vcpu);
 
                TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Unexpected exit reason: %u (%s),\n",
+                           "Unexpected exit reason: %u (%s),",
                            run->exit_reason,
                            exit_reason_str(run->exit_reason));
 
index e0ddf47362e773fbba85169b6c517ac505a3077b..167c97abff1b816dd9792b19f71c58847f433f78 100644 (file)
@@ -29,7 +29,7 @@ int main(int argc, char *argv[])
 
        xss_val = vcpu_get_msr(vcpu, MSR_IA32_XSS);
        TEST_ASSERT(xss_val == 0,
-                   "MSR_IA32_XSS should be initialized to zero\n");
+                   "MSR_IA32_XSS should be initialized to zero");
 
        vcpu_set_msr(vcpu, MSR_IA32_XSS, xss_val);
 
index 5b79758cae627593c68b9fd465451efcf7b75f9f..e64bbdf0e86eac8bf1751ee287508aca1a7ed27c 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <errno.h>
 #include <linux/landlock.h>
+#include <linux/securebits.h>
 #include <sys/capability.h>
 #include <sys/socket.h>
 #include <sys/syscall.h>
@@ -115,11 +116,16 @@ static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
                /* clang-format off */
                CAP_DAC_OVERRIDE,
                CAP_MKNOD,
+               CAP_NET_ADMIN,
+               CAP_NET_BIND_SERVICE,
                CAP_SYS_ADMIN,
                CAP_SYS_CHROOT,
-               CAP_NET_BIND_SERVICE,
                /* clang-format on */
        };
+       const unsigned int noroot = SECBIT_NOROOT | SECBIT_NOROOT_LOCKED;
+
+       if ((cap_get_secbits() & noroot) != noroot)
+               EXPECT_EQ(0, cap_set_secbits(noroot));
 
        cap_p = cap_get_proc();
        EXPECT_NE(NULL, cap_p)
@@ -137,6 +143,8 @@ static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
                        TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
                }
        }
+
+       /* Automatically resets ambient capabilities. */
        EXPECT_NE(-1, cap_set_proc(cap_p))
        {
                TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
@@ -145,6 +153,9 @@ static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
        {
                TH_LOG("Failed to cap_free: %s", strerror(errno));
        }
+
+       /* Quickly checks that ambient capabilities are cleared. */
+       EXPECT_NE(-1, cap_get_ambient(caps[0]));
 }
 
 /* We cannot put such helpers in a library because of kselftest_harness.h . */
@@ -158,8 +169,9 @@ static void __maybe_unused drop_caps(struct __test_metadata *const _metadata)
        _init_caps(_metadata, true);
 }
 
-static void _effective_cap(struct __test_metadata *const _metadata,
-                          const cap_value_t caps, const cap_flag_value_t value)
+static void _change_cap(struct __test_metadata *const _metadata,
+                       const cap_flag_t flag, const cap_value_t cap,
+                       const cap_flag_value_t value)
 {
        cap_t cap_p;
 
@@ -168,7 +180,7 @@ static void _effective_cap(struct __test_metadata *const _metadata,
        {
                TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
        }
-       EXPECT_NE(-1, cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &caps, value))
+       EXPECT_NE(-1, cap_set_flag(cap_p, flag, 1, &cap, value))
        {
                TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
        }
@@ -183,15 +195,35 @@ static void _effective_cap(struct __test_metadata *const _metadata,
 }
 
 static void __maybe_unused set_cap(struct __test_metadata *const _metadata,
-                                  const cap_value_t caps)
+                                  const cap_value_t cap)
 {
-       _effective_cap(_metadata, caps, CAP_SET);
+       _change_cap(_metadata, CAP_EFFECTIVE, cap, CAP_SET);
 }
 
 static void __maybe_unused clear_cap(struct __test_metadata *const _metadata,
-                                    const cap_value_t caps)
+                                    const cap_value_t cap)
+{
+       _change_cap(_metadata, CAP_EFFECTIVE, cap, CAP_CLEAR);
+}
+
+static void __maybe_unused
+set_ambient_cap(struct __test_metadata *const _metadata, const cap_value_t cap)
+{
+       _change_cap(_metadata, CAP_INHERITABLE, cap, CAP_SET);
+
+       EXPECT_NE(-1, cap_set_ambient(cap, CAP_SET))
+       {
+               TH_LOG("Failed to set ambient capability %d: %s", cap,
+                      strerror(errno));
+       }
+}
+
+static void __maybe_unused clear_ambient_cap(
+       struct __test_metadata *const _metadata, const cap_value_t cap)
 {
-       _effective_cap(_metadata, caps, CAP_CLEAR);
+       EXPECT_EQ(1, cap_get_ambient(cap));
+       _change_cap(_metadata, CAP_INHERITABLE, cap, CAP_CLEAR);
+       EXPECT_EQ(0, cap_get_ambient(cap));
 }
 
 /* Receives an FD from a UNIX socket. Returns the received FD, or -errno. */
index 50818904397c577e6953b7fd66bbfe894827b120..2d6d9b43d958cfb7c247e2cfa1fdbdf7a48c4c08 100644 (file)
@@ -241,9 +241,11 @@ struct mnt_opt {
        const char *const data;
 };
 
-const struct mnt_opt mnt_tmp = {
+#define MNT_TMP_DATA "size=4m,mode=700"
+
+static const struct mnt_opt mnt_tmp = {
        .type = "tmpfs",
-       .data = "size=4m,mode=700",
+       .data = MNT_TMP_DATA,
 };
 
 static int mount_opt(const struct mnt_opt *const mnt, const char *const target)
@@ -4632,7 +4634,10 @@ FIXTURE_VARIANT(layout3_fs)
 /* clang-format off */
 FIXTURE_VARIANT_ADD(layout3_fs, tmpfs) {
        /* clang-format on */
-       .mnt = mnt_tmp,
+       .mnt = {
+               .type = "tmpfs",
+               .data = MNT_TMP_DATA,
+       },
        .file_path = file1_s1d1,
 };
 
index ea5f727dd25778df7def21365eae073981ee08fe..936cfc879f1d2c419195338a8af04c095fe770f8 100644 (file)
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <sys/prctl.h>
 #include <sys/socket.h>
+#include <sys/syscall.h>
 #include <sys/un.h>
 
 #include "common.h"
@@ -54,6 +55,11 @@ struct service_fixture {
        };
 };
 
+static pid_t sys_gettid(void)
+{
+       return syscall(__NR_gettid);
+}
+
 static int set_service(struct service_fixture *const srv,
                       const struct protocol_variant prot,
                       const unsigned short index)
@@ -88,7 +94,7 @@ static int set_service(struct service_fixture *const srv,
        case AF_UNIX:
                srv->unix_addr.sun_family = prot.domain;
                sprintf(srv->unix_addr.sun_path,
-                       "_selftests-landlock-net-tid%d-index%d", gettid(),
+                       "_selftests-landlock-net-tid%d-index%d", sys_gettid(),
                        index);
                srv->unix_addr_len = SUN_LEN(&srv->unix_addr);
                srv->unix_addr.sun_path[0] = '\0';
@@ -101,8 +107,11 @@ static void setup_loopback(struct __test_metadata *const _metadata)
 {
        set_cap(_metadata, CAP_SYS_ADMIN);
        ASSERT_EQ(0, unshare(CLONE_NEWNET));
-       ASSERT_EQ(0, system("ip link set dev lo up"));
        clear_cap(_metadata, CAP_SYS_ADMIN);
+
+       set_ambient_cap(_metadata, CAP_NET_ADMIN);
+       ASSERT_EQ(0, system("ip link set dev lo up"));
+       clear_ambient_cap(_metadata, CAP_NET_ADMIN);
 }
 
 static bool is_restricted(const struct protocol_variant *const prot,
index cde9a91c479716e178c569cac18bedc9698357b6..2db9d15cd45feafc007669ae358372249c74151a 100755 (executable)
@@ -122,7 +122,9 @@ do_netperf() {
        local netns=$1
 
        [ "$NF" = "6" ] && serip=$SERVER_IP6
-       ip net exec $netns netperf -$NF -t TCP_STREAM -H $serip 2>&1 >/dev/null
+
+       # use large write to be sure to generate big tcp packets
+       ip net exec $netns netperf -$NF -t TCP_STREAM -l 1 -H $serip -- -m 262144 2>&1 >/dev/null
 }
 
 do_test() {
index f30bd57d5e38744de09a86cab47ed4999ba46e25..8bc23fb4c82b71c88c6a0f292e8735b831a5d03f 100755 (executable)
@@ -89,7 +89,7 @@ for ovr in setsock cmsg both diff; do
        check_result $? 0 "TCLASS $prot $ovr - pass"
 
        while [ -d /proc/$BG ]; do
-           $NSEXE ./cmsg_sender -6 -p u $TGT6 1234
+           $NSEXE ./cmsg_sender -6 -p $p $m $((TOS2)) $TGT6 1234
        done
 
        tcpdump -r $TMPF -v 2>&1 | grep "class $TOS2" >> /dev/null
@@ -126,7 +126,7 @@ for ovr in setsock cmsg both diff; do
        check_result $? 0 "HOPLIMIT $prot $ovr - pass"
 
        while [ -d /proc/$BG ]; do
-           $NSEXE ./cmsg_sender -6 -p u $TGT6 1234
+           $NSEXE ./cmsg_sender -6 -p $p $m $LIM $TGT6 1234
        done
 
        tcpdump -r $TMPF -v 2>&1 | grep "hlim $LIM[^0-9]" >> /dev/null
index 3b749addd364040491010ab9d4b50a19c4e3b643..5e4390cac17eda2c96d35c5cdcdf6899610e4367 100644 (file)
@@ -24,10 +24,14 @@ CONFIG_IFB=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_ESP=y
 CONFIG_INET_ESP_OFFLOAD=y
+CONFIG_NET_FOU=y
+CONFIG_NET_FOU_IP_TUNNELS=y
 CONFIG_IP_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_ADVANCED=y
 CONFIG_NF_CONNTRACK=m
+CONFIG_IPV6_SIT=y
+CONFIG_IP_DCCP=m
 CONFIG_NF_NAT=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP_NF_IPTABLES=m
@@ -62,6 +66,7 @@ CONFIG_NET_CLS_MATCHALL=m
 CONFIG_NET_CLS_U32=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
+CONFIG_NET_IPIP=y
 CONFIG_NET_SCH_FQ_CODEL=m
 CONFIG_NET_SCH_HTB=m
 CONFIG_NET_SCH_FQ=m
@@ -78,7 +83,6 @@ CONFIG_TLS=m
 CONFIG_TRACEPOINTS=y
 CONFIG_NET_DROP_MONITOR=m
 CONFIG_NETDEVSIM=m
-CONFIG_NET_FOU=m
 CONFIG_MPLS_ROUTING=m
 CONFIG_MPLS_IPTUNNEL=m
 CONFIG_NET_SCH_INGRESS=m
index 9af9f6964808baee53e69c51ad1adb4128fc700a..c62331b2e006069e8812dedf797968c24726493d 100755 (executable)
@@ -327,10 +327,10 @@ locked_port_mab_redirect()
        RET=0
        check_port_mab_support || return 0
 
-       bridge link set dev $swp1 learning on locked on mab on
        tc qdisc add dev $swp1 clsact
        tc filter add dev $swp1 ingress protocol all pref 1 handle 101 flower \
                action mirred egress redirect dev $swp2
+       bridge link set dev $swp1 learning on locked on mab on
 
        ping_do $h1 192.0.2.2
        check_err $? "Ping did not work with redirection"
@@ -349,8 +349,8 @@ locked_port_mab_redirect()
        check_err $? "Locked entry not created after deleting filter"
 
        bridge fdb del `mac_get $h1` vlan 1 dev $swp1 master
-       tc qdisc del dev $swp1 clsact
        bridge link set dev $swp1 learning off locked off mab off
+       tc qdisc del dev $swp1 clsact
 
        log_test "Locked port MAB redirect"
 }
index 61348f71728cd54537f49e17b192e08514323b4c..d9d587454d207931a539f59be15cbc63d471888f 100755 (executable)
@@ -329,7 +329,7 @@ __cfg_test_port_ip_star_g()
 
        bridge -d -s mdb get dev br0 grp $grp vid 10 | grep -q " 0.00"
        check_err $? "(*, G) \"permanent\" entry has a pending group timer"
-       bridge -d -s mdb get dev br0 grp $grp vid 10 | grep -q "\/0.00"
+       bridge -d -s mdb get dev br0 grp $grp vid 10 | grep -q "/0.00"
        check_err $? "\"permanent\" source entry has a pending source timer"
 
        bridge mdb del dev br0 port $swp1 grp $grp vid 10
@@ -346,7 +346,7 @@ __cfg_test_port_ip_star_g()
 
        bridge -d -s mdb get dev br0 grp $grp vid 10 | grep -q " 0.00"
        check_fail $? "(*, G) EXCLUDE entry does not have a pending group timer"
-       bridge -d -s mdb get dev br0 grp $grp vid 10 | grep -q "\/0.00"
+       bridge -d -s mdb get dev br0 grp $grp vid 10 | grep -q "/0.00"
        check_err $? "\"blocked\" source entry has a pending source timer"
 
        bridge mdb del dev br0 port $swp1 grp $grp vid 10
@@ -363,7 +363,7 @@ __cfg_test_port_ip_star_g()
 
        bridge -d -s mdb get dev br0 grp $grp vid 10 | grep -q " 0.00"
        check_err $? "(*, G) INCLUDE entry has a pending group timer"
-       bridge -d -s mdb get dev br0 grp $grp vid 10 | grep -q "\/0.00"
+       bridge -d -s mdb get dev br0 grp $grp vid 10 | grep -q "/0.00"
        check_fail $? "Source entry does not have a pending source timer"
 
        bridge mdb del dev br0 port $swp1 grp $grp vid 10
@@ -1252,14 +1252,17 @@ fwd_test()
        echo
        log_info "# Forwarding tests"
 
+       # Set the Max Response Delay to 100 centiseconds (1 second) so that the
+       # bridge will start forwarding according to its MDB soon after a
+       # multicast querier is enabled.
+       ip link set dev br0 type bridge mcast_query_response_interval 100
+
        # Forwarding according to MDB entries only takes place when the bridge
        # detects that there is a valid querier in the network. Set the bridge
        # as the querier and assign it a valid IPv6 link-local address to be
        # used as the source address for MLD queries.
        ip -6 address add fe80::1/64 nodad dev br0
        ip link set dev br0 type bridge mcast_querier 1
-       # Wait the default Query Response Interval (10 seconds) for the bridge
-       # to determine that there are no other queriers in the network.
        sleep 10
 
        fwd_test_host
@@ -1267,6 +1270,7 @@ fwd_test()
 
        ip link set dev br0 type bridge mcast_querier 0
        ip -6 address del fe80::1/64 dev br0
+       ip link set dev br0 type bridge mcast_query_response_interval 1000
 }
 
 ctrl_igmpv3_is_in_test()
index 20a7cb7222b8baa4062a769f2f0d27daf2b00cfd..c2420bb72c128119f005de590e36952dc5960f36 100755 (executable)
@@ -209,14 +209,17 @@ test_l2_miss_multicast()
        # both registered and unregistered multicast traffic.
        bridge link set dev $swp2 mcast_router 2
 
+       # Set the Max Response Delay to 100 centiseconds (1 second) so that the
+       # bridge will start forwarding according to its MDB soon after a
+       # multicast querier is enabled.
+       ip link set dev br1 type bridge mcast_query_response_interval 100
+
        # Forwarding according to MDB entries only takes place when the bridge
        # detects that there is a valid querier in the network. Set the bridge
        # as the querier and assign it a valid IPv6 link-local address to be
        # used as the source address for MLD queries.
        ip link set dev br1 type bridge mcast_querier 1
        ip -6 address add fe80::1/64 nodad dev br1
-       # Wait the default Query Response Interval (10 seconds) for the bridge
-       # to determine that there are no other queriers in the network.
        sleep 10
 
        test_l2_miss_multicast_ipv4
@@ -224,6 +227,7 @@ test_l2_miss_multicast()
 
        ip -6 address del fe80::1/64 dev br1
        ip link set dev br1 type bridge mcast_querier 0
+       ip link set dev br1 type bridge mcast_query_response_interval 1000
        bridge link set dev $swp2 mcast_router 1
 }
 
index 19352f106c1dff1b316ef9991e32c9d78142ac45..02c21ff4ca81fddc89ca697fe3d3f04a5dc792c8 100755 (executable)
@@ -31,6 +31,11 @@ run_test() {
       1>>log.txt
     wait "${server_pid}"
     exit_code=$?
+    if [[ ${test} == "large" && -n "${KSFT_MACHINE_SLOW}" && \
+          ${exit_code} -ne 0 ]]; then
+        echo "Ignoring errors due to slow environment" 1>&2
+        exit_code=0
+    fi
     if [[ "${exit_code}" -eq 0 ]]; then
         break;
     fi
index 0f217a1cc837de22de278d15f7cfb6bbdb372c50..6ebd58869a637227319524c0bdc69fe2495a37c9 100644 (file)
 #define IP_LOCAL_PORT_RANGE 51
 #endif
 
+#ifndef IPPROTO_MPTCP
+#define IPPROTO_MPTCP 262
+#endif
+
 static __u32 pack_port_range(__u16 lo, __u16 hi)
 {
        return (hi << 16) | (lo << 0);
index 4fe0befa13fbc6aa52fed84080615362ff92724f..6596fe03c77f43742e5676e5ccd1e46ba96e5c12 100644 (file)
@@ -8,13 +8,16 @@ wait_local_port_listen()
        local listener_ns="${1}"
        local port="${2}"
        local protocol="${3}"
-       local port_hex
+       local pattern
        local i
 
-       port_hex="$(printf "%04X" "${port}")"
+       pattern=":$(printf "%04X" "${port}") "
+
+       # for tcp protocol additionally check the socket state
+       [ ${protocol} = "tcp" ] && pattern="${pattern}0A"
        for i in $(seq 10); do
-               if ip netns exec "${listener_ns}" cat /proc/net/"${protocol}"* | \
-                  grep -q "${port_hex}"; then
+               if ip netns exec "${listener_ns}" awk '{print $2" "$4}' \
+                  /proc/net/"${protocol}"* | grep -q "${pattern}"; then
                        break
                fi
                sleep 0.1
index f8499d4c87f3f763e774619666e00ce6a17d333b..36e40256ab92a696de62339dd7c7342df3468372 100755 (executable)
@@ -502,7 +502,20 @@ test_netlink_checks () {
            wc -l) == 2 ] || \
              return 1
 
+       info "Checking clone depth"
        ERR_MSG="Flow actions may not be safe on all matching packets"
+       PRE_TEST=$(dmesg | grep -c "${ERR_MSG}")
+       ovs_add_flow "test_netlink_checks" nv0 \
+               'in_port(1),eth(),eth_type(0x800),ipv4()' \
+               'clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(drop)))))))))))))))))' \
+               >/dev/null 2>&1 && return 1
+       POST_TEST=$(dmesg | grep -c "${ERR_MSG}")
+
+       if [ "$PRE_TEST" == "$POST_TEST" ]; then
+               info "failed - clone depth too large"
+               return 1
+       fi
+
        PRE_TEST=$(dmesg | grep -c "${ERR_MSG}")
        ovs_add_flow "test_netlink_checks" nv0 \
                'in_port(1),eth(),eth_type(0x0806),arp()' 'drop(0),2' \
index b97e621face958838f1ad5cf2d12dfc5875db4f4..5e0e539a323d55a44802495ca356661ef8de783a 100644 (file)
@@ -299,7 +299,7 @@ class ovsactions(nla):
         ("OVS_ACTION_ATTR_PUSH_NSH", "none"),
         ("OVS_ACTION_ATTR_POP_NSH", "flag"),
         ("OVS_ACTION_ATTR_METER", "none"),
-        ("OVS_ACTION_ATTR_CLONE", "none"),
+        ("OVS_ACTION_ATTR_CLONE", "recursive"),
         ("OVS_ACTION_ATTR_CHECK_PKT_LEN", "none"),
         ("OVS_ACTION_ATTR_ADD_MPLS", "none"),
         ("OVS_ACTION_ATTR_DEC_TTL", "none"),
@@ -465,29 +465,42 @@ class ovsactions(nla):
                     print_str += "pop_mpls"
             else:
                 datum = self.get_attr(field[0])
-                print_str += datum.dpstr(more)
+                if field[0] == "OVS_ACTION_ATTR_CLONE":
+                    print_str += "clone("
+                    print_str += datum.dpstr(more)
+                    print_str += ")"
+                else:
+                    print_str += datum.dpstr(more)
 
         return print_str
 
     def parse(self, actstr):
+        totallen = len(actstr)
         while len(actstr) != 0:
             parsed = False
+            parencount = 0
             if actstr.startswith("drop"):
                 # If no reason is provided, the implicit drop is used (i.e no
                 # action). If some reason is given, an explicit action is used.
-                actstr, reason = parse_extract_field(
-                    actstr,
-                    "drop(",
-                    "([0-9]+)",
-                    lambda x: int(x, 0),
-                    False,
-                    None,
-                )
+                reason = None
+                if actstr.startswith("drop("):
+                    parencount += 1
+
+                    actstr, reason = parse_extract_field(
+                        actstr,
+                        "drop(",
+                        "([0-9]+)",
+                        lambda x: int(x, 0),
+                        False,
+                        None,
+                    )
+
                 if reason is not None:
                     self["attrs"].append(["OVS_ACTION_ATTR_DROP", reason])
                     parsed = True
                 else:
-                    return
+                    actstr = actstr[len("drop"): ]
+                    return (totallen - len(actstr))
 
             elif parse_starts_block(actstr, "^(\d+)", False, True):
                 actstr, output = parse_extract_field(
@@ -504,6 +517,7 @@ class ovsactions(nla):
                     False,
                     0,
                 )
+                parencount += 1
                 self["attrs"].append(["OVS_ACTION_ATTR_RECIRC", recircid])
                 parsed = True
 
@@ -516,12 +530,22 @@ class ovsactions(nla):
 
             for flat_act in parse_flat_map:
                 if parse_starts_block(actstr, flat_act[0], False):
-                    actstr += len(flat_act[0])
+                    actstr = actstr[len(flat_act[0]):]
                     self["attrs"].append([flat_act[1]])
                     actstr = actstr[strspn(actstr, ", ") :]
                     parsed = True
 
-            if parse_starts_block(actstr, "ct(", False):
+            if parse_starts_block(actstr, "clone(", False):
+                parencount += 1
+                subacts = ovsactions()
+                actstr = actstr[len("clone("):]
+                parsedLen = subacts.parse(actstr)
+                lst = []
+                self["attrs"].append(("OVS_ACTION_ATTR_CLONE", subacts))
+                actstr = actstr[parsedLen:]
+                parsed = True
+            elif parse_starts_block(actstr, "ct(", False):
+                parencount += 1
                 actstr = actstr[len("ct(") :]
                 ctact = ovsactions.ctact()
 
@@ -553,6 +577,7 @@ class ovsactions(nla):
                         natact = ovsactions.ctact.natattr()
 
                         if actstr.startswith("("):
+                            parencount += 1
                             t = None
                             actstr = actstr[1:]
                             if actstr.startswith("src"):
@@ -607,15 +632,29 @@ class ovsactions(nla):
                                     actstr = actstr[strspn(actstr, ", ") :]
 
                         ctact["attrs"].append(["OVS_CT_ATTR_NAT", natact])
-                        actstr = actstr[strspn(actstr, ",) ") :]
+                        actstr = actstr[strspn(actstr, ", ") :]
 
                 self["attrs"].append(["OVS_ACTION_ATTR_CT", ctact])
                 parsed = True
 
-            actstr = actstr[strspn(actstr, "), ") :]
+            actstr = actstr[strspn(actstr, ", ") :]
+            while parencount > 0:
+                parencount -= 1
+                actstr = actstr[strspn(actstr, " "):]
+                if len(actstr) and actstr[0] != ")":
+                    raise ValueError("Action str: '%s' unbalanced" % actstr)
+                actstr = actstr[1:]
+
+            if len(actstr) and actstr[0] == ")":
+                return (totallen - len(actstr))
+
+            actstr = actstr[strspn(actstr, ", ") :]
+
             if not parsed:
                 raise ValueError("Action str: '%s' not supported" % actstr)
 
+        return (totallen - len(actstr))
+
 
 class ovskey(nla):
     nla_flags = NLA_F_NESTED
@@ -2111,6 +2150,8 @@ def main(argv):
     ovsflow = OvsFlow()
     ndb = NDB()
 
+    sys.setrecursionlimit(100000)
+
     if hasattr(args, "showdp"):
         found = False
         for iface in ndb.interfaces:
index 3f118e3f1c66d636c6379485da9fcea4fbc6aff8..cfc84958025a61e7ee24a3675a0969e0e3c7cd52 100755 (executable)
 #      Same as above but with IPv6
 
 source lib.sh
+source net_helper.sh
 
 PAUSE_ON_FAIL=no
 VERBOSE=0
@@ -1335,12 +1336,14 @@ test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception() {
                else
                        TCPDST="TCP:[${dst}]:50000"
                fi
-               ${ns_b} socat -T 3 -u -6 TCP-LISTEN:50000 STDOUT > $tmpoutfile &
+               ${ns_b} socat -T 3 -u -6 TCP-LISTEN:50000,reuseaddr STDOUT > $tmpoutfile &
+               local socat_pid=$!
 
-               sleep 1
+               wait_local_port_listen ${NS_B} 50000 tcp
 
                dd if=/dev/zero status=none bs=1M count=1 | ${target} socat -T 3 -u STDIN $TCPDST,connect-timeout=3
 
+               wait ${socat_pid}
                size=$(du -sb $tmpoutfile)
                size=${size%%/tmp/*}
 
@@ -1954,6 +1957,13 @@ check_command() {
        return 0
 }
 
+check_running() {
+       pid=${1}
+       cmd=${2}
+
+       [ "$(cat /proc/${pid}/cmdline 2>/dev/null | tr -d '\0')" = "{cmd}" ]
+}
+
 test_cleanup_vxlanX_exception() {
        outer="${1}"
        encap="vxlan"
@@ -1984,11 +1994,12 @@ test_cleanup_vxlanX_exception() {
 
        ${ns_a} ip link del dev veth_A-R1 &
        iplink_pid=$!
-       sleep 1
-       if [ "$(cat /proc/${iplink_pid}/cmdline 2>/dev/null | tr -d '\0')" = "iplinkdeldevveth_A-R1" ]; then
-               err "  can't delete veth device in a timely manner, PMTU dst likely leaked"
-               return 1
-       fi
+       for i in $(seq 1 20); do
+               check_running ${iplink_pid} "iplinkdeldevveth_A-R1" || return 0
+               sleep 0.1
+       done
+       err "  can't delete veth device in a timely manner, PMTU dst likely leaked"
+       return 1
 }
 
 test_cleanup_ipv6_exception() {
index 4667d74579d135eb74d701d79baa3036c88f2635..874a2952aa8ee16b1841bdd7e2930e54a1c99303 100755 (executable)
@@ -440,7 +440,6 @@ kci_test_encap_vxlan()
        local ret=0
        vxlan="test-vxlan0"
        vlan="test-vlan0"
-       testns="$1"
        run_cmd ip -netns "$testns" link add "$vxlan" type vxlan id 42 group 239.1.1.1 \
                dev "$devdummy" dstport 4789
        if [ $? -ne 0 ]; then
@@ -485,7 +484,6 @@ kci_test_encap_fou()
 {
        local ret=0
        name="test-fou"
-       testns="$1"
        run_cmd_grep 'Usage: ip fou' ip fou help
        if [ $? -ne 0 ];then
                end_test "SKIP: fou: iproute2 too old"
@@ -526,8 +524,8 @@ kci_test_encap()
        run_cmd ip -netns "$testns" link set lo up
        run_cmd ip -netns "$testns" link add name "$devdummy" type dummy
        run_cmd ip -netns "$testns" link set "$devdummy" up
-       run_cmd kci_test_encap_vxlan "$testns"
-       run_cmd kci_test_encap_fou "$testns"
+       run_cmd kci_test_encap_vxlan
+       run_cmd kci_test_encap_fou
 
        ip netns del "$testns"
        return $ret
index 3f06f4d286a988f15ccbc006f8015b24a07be3f0..5e861ad32a42e11b680236b4a016ed952caf5914 100755 (executable)
@@ -5,6 +5,7 @@
 
 set -e
 
+readonly ksft_skip=4
 readonly DEV="veth0"
 readonly BIN="./so_txtime"
 
@@ -46,7 +47,7 @@ ip -netns "${NS2}" addr add 192.168.1.2/24 dev "${DEV}"
 ip -netns "${NS1}" addr add       fd::1/64 dev "${DEV}" nodad
 ip -netns "${NS2}" addr add       fd::2/64 dev "${DEV}" nodad
 
-do_test() {
+run_test() {
        local readonly IP="$1"
        local readonly CLOCK="$2"
        local readonly TXARGS="$3"
@@ -64,12 +65,25 @@ do_test() {
        fi
 
        local readonly START="$(date +%s%N --date="+ 0.1 seconds")"
+
        ip netns exec "${NS2}" "${BIN}" -"${IP}" -c "${CLOCK}" -t "${START}" -S "${SADDR}" -D "${DADDR}" "${RXARGS}" -r &
        ip netns exec "${NS1}" "${BIN}" -"${IP}" -c "${CLOCK}" -t "${START}" -S "${SADDR}" -D "${DADDR}" "${TXARGS}"
        wait "$!"
 }
 
+do_test() {
+       run_test $@
+       [ $? -ne 0 ] && ret=1
+}
+
+do_fail_test() {
+       run_test $@
+       [ $? -eq 0 ] && ret=1
+}
+
 ip netns exec "${NS1}" tc qdisc add dev "${DEV}" root fq
+set +e
+ret=0
 do_test 4 mono a,-1 a,-1
 do_test 6 mono a,0 a,0
 do_test 6 mono a,10 a,10
@@ -77,13 +91,20 @@ do_test 4 mono a,10,b,20 a,10,b,20
 do_test 6 mono a,20,b,10 b,20,a,20
 
 if ip netns exec "${NS1}" tc qdisc replace dev "${DEV}" root etf clockid CLOCK_TAI delta 400000; then
-       ! do_test 4 tai a,-1 a,-1
-       ! do_test 6 tai a,0 a,0
+       do_fail_test 4 tai a,-1 a,-1
+       do_fail_test 6 tai a,0 a,0
        do_test 6 tai a,10 a,10
        do_test 4 tai a,10,b,20 a,10,b,20
        do_test 6 tai a,20,b,10 b,10,a,20
 else
        echo "tc ($(tc -V)) does not support qdisc etf. skipping"
+       [ $ret -eq 0 ] && ret=$ksft_skip
 fi
 
-echo OK. All tests passed
+if [ $ret -eq 0 ]; then
+       echo OK. All tests passed
+elif [[ $ret -ne $ksft_skip && -n "$KSFT_MACHINE_SLOW" ]]; then
+       echo "Ignoring errors due to slow environment" 1>&2
+       ret=0
+fi
+exit $ret
index c5b568cd7d901ce19d26cc0228dc7089581bb7f1..6b59a652159f7754417471c066a06bd4eb511a41 100644 (file)
@@ -110,9 +110,9 @@ static void try_accept(const char *tst_name, unsigned int port,
                test_tcp_ao_counters_cmp(tst_name, &ao_cnt1, &ao_cnt2, cnt_expected);
 
 out:
-       synchronize_threads(); /* close() */
+       synchronize_threads(); /* test_kill_sk() */
        if (sk > 0)
-               close(sk);
+               test_kill_sk(sk);
 }
 
 static void server_add_routes(void)
@@ -302,10 +302,10 @@ static void try_connect(const char *tst_name, unsigned int port,
                test_ok("%s: connected", tst_name);
 
 out:
-       synchronize_threads(); /* close() */
+       synchronize_threads(); /* test_kill_sk() */
        /* _test_connect_socket() cleans up on failure */
        if (ret > 0)
-               close(sk);
+               test_kill_sk(sk);
 }
 
 #define PREINSTALL_MD5_FIRST   BIT(0)
@@ -486,10 +486,10 @@ static void try_to_add(const char *tst_name, unsigned int port,
        }
 
 out:
-       synchronize_threads(); /* close() */
+       synchronize_threads(); /* test_kill_sk() */
        /* _test_connect_socket() cleans up on failure */
        if (ret > 0)
-               close(sk);
+               test_kill_sk(sk);
 }
 
 static void client_add_ip(union tcp_addr *client, const char *ip)
index 70a7d87ba2d21cecf6d76f7d184e0902e7b6d3e9..1b3f89e2b86e6aac2f9d631bb9bb22265c3f1734 100755 (executable)
@@ -124,6 +124,16 @@ tc_check_packets()
        [[ $pkts == $count ]]
 }
 
+bridge_link_check()
+{
+       local ns=$1; shift
+       local dev=$1; shift
+       local state=$1; shift
+
+       bridge -n $ns -d -j link show dev $dev | \
+               jq -e ".[][\"state\"] == \"$state\"" &> /dev/null
+}
+
 ################################################################################
 # Setup
 
@@ -259,6 +269,7 @@ backup_port()
        log_test $? 0 "No forwarding out of vx0"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier off"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
        log_test $? 0 "swp1 carrier off"
 
        run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
@@ -268,6 +279,7 @@ backup_port()
        log_test $? 0 "No forwarding out of vx0"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier on"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 forwarding
        log_test $? 0 "swp1 carrier on"
 
        # Configure vx0 as the backup port of swp1 and check that packets are
@@ -284,6 +296,7 @@ backup_port()
        log_test $? 0 "No forwarding out of vx0"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier off"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
        log_test $? 0 "swp1 carrier off"
 
        run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
@@ -293,6 +306,7 @@ backup_port()
        log_test $? 0 "Forwarding out of vx0"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier on"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 forwarding
        log_test $? 0 "swp1 carrier on"
 
        run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
@@ -314,6 +328,7 @@ backup_port()
        log_test $? 0 "No forwarding out of vx0"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier off"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
        log_test $? 0 "swp1 carrier off"
 
        run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
@@ -369,6 +384,7 @@ backup_nhid()
        log_test $? 0 "No forwarding out of vx0"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier off"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
        log_test $? 0 "swp1 carrier off"
 
        run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
@@ -382,6 +398,7 @@ backup_nhid()
        log_test $? 0 "Forwarding using VXLAN FDB entry"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier on"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 forwarding
        log_test $? 0 "swp1 carrier on"
 
        # Configure nexthop ID 10 as the backup nexthop ID of swp1 and check
@@ -398,6 +415,7 @@ backup_nhid()
        log_test $? 0 "No forwarding out of vx0"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier off"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
        log_test $? 0 "swp1 carrier off"
 
        run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
@@ -411,6 +429,7 @@ backup_nhid()
        log_test $? 0 "No forwarding using VXLAN FDB entry"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier on"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 forwarding
        log_test $? 0 "swp1 carrier on"
 
        run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
@@ -441,6 +460,7 @@ backup_nhid()
        log_test $? 0 "No forwarding using VXLAN FDB entry"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier off"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
        log_test $? 0 "swp1 carrier off"
 
        run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
@@ -497,6 +517,7 @@ backup_nhid_invalid()
        log_test $? 0 "Valid nexthop as backup nexthop"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier off"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
        log_test $? 0 "swp1 carrier off"
 
        run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
@@ -604,7 +625,9 @@ backup_nhid_ping()
        run_cmd "bridge -n $sw2 link set dev swp1 backup_nhid 10"
 
        run_cmd "ip -n $sw1 link set dev swp1 carrier off"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
        run_cmd "ip -n $sw2 link set dev swp1 carrier off"
+       busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw2 swp1 disabled
 
        run_cmd "ip netns exec $sw1 ping -i 0.1 -c 10 -w $PING_TIMEOUT 192.0.2.66"
        log_test $? 0 "Ping with backup nexthop ID"
index 7799e042a9719cda33ea7d004d2ae4a2ec608a4f..49c84602707f89d6f901ee60b63c4e5dfe75f8c8 100644 (file)
@@ -1002,12 +1002,12 @@ TEST_F(tls, recv_partial)
 
        memset(recv_mem, 0, sizeof(recv_mem));
        EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
-       EXPECT_NE(recv(self->cfd, recv_mem, strlen(test_str_first),
-                      MSG_WAITALL), -1);
+       EXPECT_EQ(recv(self->cfd, recv_mem, strlen(test_str_first),
+                      MSG_WAITALL), strlen(test_str_first));
        EXPECT_EQ(memcmp(test_str_first, recv_mem, strlen(test_str_first)), 0);
        memset(recv_mem, 0, sizeof(recv_mem));
-       EXPECT_NE(recv(self->cfd, recv_mem, strlen(test_str_second),
-                      MSG_WAITALL), -1);
+       EXPECT_EQ(recv(self->cfd, recv_mem, strlen(test_str_second),
+                      MSG_WAITALL), strlen(test_str_second));
        EXPECT_EQ(memcmp(test_str_second, recv_mem, strlen(test_str_second)),
                  0);
 }
@@ -1874,13 +1874,13 @@ TEST_F(tls_err, poll_partial_rec_async)
                /* Child should sleep in poll(), never get a wake */
                pfd.fd = self->cfd2;
                pfd.events = POLLIN;
-               EXPECT_EQ(poll(&pfd, 1, 5), 0);
+               EXPECT_EQ(poll(&pfd, 1, 20), 0);
 
                EXPECT_EQ(write(p[1], &token, 1), 1); /* Barrier #1 */
 
                pfd.fd = self->cfd2;
                pfd.events = POLLIN;
-               EXPECT_EQ(poll(&pfd, 1, 5), 1);
+               EXPECT_EQ(poll(&pfd, 1, 20), 1);
 
                exit(!_metadata->passed);
        }
index d6b9c759043ca8219be27ce953b94722ae1492c6..9cd5e885e91f74b01007cf14bbdb9808aa04c632 100755 (executable)
@@ -39,6 +39,10 @@ create_ns() {
        for ns in $NS_SRC $NS_DST; do
                ip netns add $ns
                ip -n $ns link set dev lo up
+
+               # disable route solicitations to decrease 'noise' traffic
+               ip netns exec $ns sysctl -qw net.ipv6.conf.default.router_solicitations=0
+               ip netns exec $ns sysctl -qw net.ipv6.conf.all.router_solicitations=0
        done
 
        ip link add name veth$SRC type veth peer name veth$DST
@@ -80,6 +84,12 @@ create_vxlan_pair() {
                create_vxlan_endpoint $BASE$ns veth$ns $BM_NET_V6$((3 - $ns)) vxlan6$ns 6
                ip -n $BASE$ns addr add dev vxlan6$ns $OL_NET_V6$ns/24 nodad
        done
+
+       # preload neighbur cache, do avoid some noisy traffic
+       local addr_dst=$(ip -j -n $BASE$DST link show dev vxlan6$DST  |jq -r '.[]["address"]')
+       local addr_src=$(ip -j -n $BASE$SRC link show dev vxlan6$SRC  |jq -r '.[]["address"]')
+       ip -n $BASE$DST neigh add dev vxlan6$DST lladdr $addr_src $OL_NET_V6$SRC
+       ip -n $BASE$SRC neigh add dev vxlan6$SRC lladdr $addr_dst $OL_NET_V6$DST
 }
 
 is_ipv6() {
@@ -119,7 +129,7 @@ run_test() {
        # not enable GRO
        ip netns exec $NS_DST $ipt -A INPUT -p udp --dport 4789
        ip netns exec $NS_DST $ipt -A INPUT -p udp --dport 8000
-       ip netns exec $NS_DST ./udpgso_bench_rx -C 1000 -R 10 -n 10 -l 1300 $rx_args &
+       ip netns exec $NS_DST ./udpgso_bench_rx -C 2000 -R 100 -n 10 -l 1300 $rx_args &
        local spid=$!
        wait_local_port_listen "$NS_DST" 8000 udp
        ip netns exec $NS_SRC ./udpgso_bench_tx $family -M 1 -s 13000 -S 1300 -D $dst
@@ -168,7 +178,7 @@ run_bench() {
        # bind the sender and the receiver to different CPUs to try
        # get reproducible results
        ip netns exec $NS_DST bash -c "echo 2 > /sys/class/net/veth$DST/queues/rx-0/rps_cpus"
-       ip netns exec $NS_DST taskset 0x2 ./udpgso_bench_rx -C 1000 -R 10  &
+       ip netns exec $NS_DST taskset 0x2 ./udpgso_bench_rx -C 2000 -R 100  &
        local spid=$!
        wait_local_port_listen "$NS_DST" 8000 udp
        ip netns exec $NS_SRC taskset 0x1 ./udpgso_bench_tx $family -l 3 -S 1300 -D $dst
index f35a924d4a3030780447f2cc137f6ff373ed693c..1cbadd267c963c0c067308d3fb16493625e8f1b7 100644 (file)
@@ -375,7 +375,7 @@ static void do_recv(void)
                        do_flush_udp(fd);
 
                tnow = gettimeofday_ms();
-               if (tnow > treport) {
+               if (!cfg_expected_pkt_nr && tnow > treport) {
                        if (packets)
                                fprintf(stderr,
                                        "%s rx: %6lu MB/s %8lu calls/s\n",
index f18c6db13bbff402202f6bd4796b4581803e2d73..b11ea8ee67194604de4a7dcbda7539dbffe7b7a1 100644 (file)
@@ -13,7 +13,7 @@
 #include "../kselftest_harness.h"
 
 #define TEST_ZONE_ID 123
-#define CTA_FILTER_F_CTA_TUPLE_ZONE (1 << 2)
+#define NF_CT_DEFAULT_ZONE_ID 0
 
 static int reply_counter;
 
@@ -336,6 +336,9 @@ FIXTURE_SETUP(conntrack_dump_flush)
        ret = conntrack_data_generate_v4(self->sock, 0xf4f4f4f4, 0xf5f5f5f5,
                                         TEST_ZONE_ID + 2);
        EXPECT_EQ(ret, 0);
+       ret = conntrack_data_generate_v4(self->sock, 0xf6f6f6f6, 0xf7f7f7f7,
+                                        NF_CT_DEFAULT_ZONE_ID);
+       EXPECT_EQ(ret, 0);
 
        src = (struct in6_addr) {{
                .__u6_addr32 = {
@@ -395,6 +398,26 @@ FIXTURE_SETUP(conntrack_dump_flush)
                                         TEST_ZONE_ID + 2);
        EXPECT_EQ(ret, 0);
 
+       src = (struct in6_addr) {{
+               .__u6_addr32 = {
+                       0xb80d0120,
+                       0x00000000,
+                       0x00000000,
+                       0x07000000
+               }
+       }};
+       dst = (struct in6_addr) {{
+               .__u6_addr32 = {
+                       0xb80d0120,
+                       0x00000000,
+                       0x00000000,
+                       0x08000000
+               }
+       }};
+       ret = conntrack_data_generate_v6(self->sock, src, dst,
+                                        NF_CT_DEFAULT_ZONE_ID);
+       EXPECT_EQ(ret, 0);
+
        ret = conntracK_count_zone(self->sock, TEST_ZONE_ID);
        EXPECT_GE(ret, 2);
        if (ret > 2)
@@ -425,6 +448,24 @@ TEST_F(conntrack_dump_flush, test_flush_by_zone)
        EXPECT_EQ(ret, 2);
        ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 2);
        EXPECT_EQ(ret, 2);
+       ret = conntracK_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID);
+       EXPECT_EQ(ret, 2);
+}
+
+TEST_F(conntrack_dump_flush, test_flush_by_zone_default)
+{
+       int ret;
+
+       ret = conntrack_flush_zone(self->sock, NF_CT_DEFAULT_ZONE_ID);
+       EXPECT_EQ(ret, 0);
+       ret = conntracK_count_zone(self->sock, TEST_ZONE_ID);
+       EXPECT_EQ(ret, 2);
+       ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 1);
+       EXPECT_EQ(ret, 2);
+       ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 2);
+       EXPECT_EQ(ret, 2);
+       ret = conntracK_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID);
+       EXPECT_EQ(ret, 0);
 }
 
 TEST_HARNESS_MAIN
index 2456a399eb9ae1ce2a3c90c10ce1403dd23f62d1..afd18c678ff5a584a92e13ae8ee30bcba90f21ca 100644 (file)
@@ -28,10 +28,15 @@ FOPTS       :=      -flto=auto -ffat-lto-objects -fexceptions -fstack-protector-strong \
                -fasynchronous-unwind-tables -fstack-clash-protection
 WOPTS  :=      -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -Wno-maybe-uninitialized
 
+ifeq ($(CC),clang)
+  FOPTS := $(filter-out -ffat-lto-objects, $(FOPTS))
+  WOPTS := $(filter-out -Wno-maybe-uninitialized, $(WOPTS))
+endif
+
 TRACEFS_HEADERS        := $$($(PKG_CONFIG) --cflags libtracefs)
 
 CFLAGS :=      -O -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(MOPTS) $(WOPTS) $(TRACEFS_HEADERS) $(EXTRA_CFLAGS)
-LDFLAGS        :=      -ggdb $(EXTRA_LDFLAGS)
+LDFLAGS        :=      -flto=auto -ggdb $(EXTRA_LDFLAGS)
 LIBS   :=      $$($(PKG_CONFIG) --libs libtracefs)
 
 SRC    :=      $(wildcard src/*.c)
index 8f81fa007364890dd4303b047c484786a56390f2..01870d50942a19a242f6444c7b11f019b460ec4e 100644 (file)
@@ -135,8 +135,7 @@ static void osnoise_hist_update_multiple(struct osnoise_tool *tool, int cpu,
        if (params->output_divisor)
                duration = duration / params->output_divisor;
 
-       if (data->bucket_size)
-               bucket = duration / data->bucket_size;
+       bucket = duration / data->bucket_size;
 
        total_duration = duration * count;
 
@@ -480,7 +479,11 @@ static void osnoise_hist_usage(char *usage)
 
        for (i = 0; msg[i]; i++)
                fprintf(stderr, "%s\n", msg[i]);
-       exit(1);
+
+       if (usage)
+               exit(EXIT_FAILURE);
+
+       exit(EXIT_SUCCESS);
 }
 
 /*
index f7c959be8677799788eda3e577246cd3d2ec444a..457360db07673191fbc034c9fdb3193b91c4499c 100644 (file)
@@ -331,7 +331,11 @@ static void osnoise_top_usage(struct osnoise_top_params *params, char *usage)
 
        for (i = 0; msg[i]; i++)
                fprintf(stderr, "%s\n", msg[i]);
-       exit(1);
+
+       if (usage)
+               exit(EXIT_FAILURE);
+
+       exit(EXIT_SUCCESS);
 }
 
 /*
index 47d3d8b53cb2177fe7db4c39a21e630aca22fa23..dbf154082f958c146bed6537dc527f83e57993d4 100644 (file)
@@ -178,8 +178,7 @@ timerlat_hist_update(struct osnoise_tool *tool, int cpu,
        if (params->output_divisor)
                latency = latency / params->output_divisor;
 
-       if (data->bucket_size)
-               bucket = latency / data->bucket_size;
+       bucket = latency / data->bucket_size;
 
        if (!context) {
                hist = data->hist[cpu].irq;
@@ -546,7 +545,11 @@ static void timerlat_hist_usage(char *usage)
 
        for (i = 0; msg[i]; i++)
                fprintf(stderr, "%s\n", msg[i]);
-       exit(1);
+
+       if (usage)
+               exit(EXIT_FAILURE);
+
+       exit(EXIT_SUCCESS);
 }
 
 /*
index 1640f121baca50d99b94621309522d3fb824bc33..3e9af2c3868880197dc3075b74d94a15bea07d38 100644 (file)
@@ -375,7 +375,11 @@ static void timerlat_top_usage(char *usage)
 
        for (i = 0; msg[i]; i++)
                fprintf(stderr, "%s\n", msg[i]);
-       exit(1);
+
+       if (usage)
+               exit(EXIT_FAILURE);
+
+       exit(EXIT_SUCCESS);
 }
 
 /*
index c769d7b3842c0967e85f7dc1d8c6c705edd1f2dd..9ac71a66840c1bec2e944f3a9db0f427f3c7edfb 100644 (file)
@@ -238,12 +238,6 @@ static inline int sched_setattr(pid_t pid, const struct sched_attr *attr,
        return syscall(__NR_sched_setattr, pid, attr, flags);
 }
 
-static inline int sched_getattr(pid_t pid, struct sched_attr *attr,
-                               unsigned int size, unsigned int flags)
-{
-       return syscall(__NR_sched_getattr, pid, attr, size, flags);
-}
-
 int __set_sched_attr(int pid, struct sched_attr *attr)
 {
        int flags = 0;
@@ -479,13 +473,13 @@ int parse_prio(char *arg, struct sched_attr *sched_param)
                if (prio == INVALID_VAL)
                        return -1;
 
-               if (prio < sched_get_priority_min(SCHED_OTHER))
+               if (prio < MIN_NICE)
                        return -1;
-               if (prio > sched_get_priority_max(SCHED_OTHER))
+               if (prio > MAX_NICE)
                        return -1;
 
                sched_param->sched_policy   = SCHED_OTHER;
-               sched_param->sched_priority = prio;
+               sched_param->sched_nice = prio;
                break;
        default:
                return -1;
@@ -536,7 +530,7 @@ int set_cpu_dma_latency(int32_t latency)
  */
 static const int find_mount(const char *fs, char *mp, int sizeof_mp)
 {
-       char mount_point[MAX_PATH];
+       char mount_point[MAX_PATH+1];
        char type[100];
        int found = 0;
        FILE *fp;
index 04ed1e650495a357daabfe40653c1eab5e89b005..d44513e6c66a01a5fc75f472dcfb9ebbfbd57bfb 100644 (file)
@@ -9,6 +9,8 @@
  */
 #define BUFF_U64_STR_SIZE      24
 #define MAX_PATH               1024
+#define MAX_NICE               20
+#define MIN_NICE               -19
 
 #define container_of(ptr, type, member)({                      \
        const typeof(((type *)0)->member) *__mptr = (ptr);      \
index 3d0f3888a58c66816fca24b5a9d7ab2106f0e992..485f8aeddbe033f227faf32139630d2a616cbd66 100644 (file)
@@ -28,10 +28,15 @@ FOPTS       :=      -flto=auto -ffat-lto-objects -fexceptions -fstack-protector-strong \
                -fasynchronous-unwind-tables -fstack-clash-protection
 WOPTS  :=      -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -Wno-maybe-uninitialized
 
+ifeq ($(CC),clang)
+  FOPTS := $(filter-out -ffat-lto-objects, $(FOPTS))
+  WOPTS := $(filter-out -Wno-maybe-uninitialized, $(WOPTS))
+endif
+
 TRACEFS_HEADERS        := $$($(PKG_CONFIG) --cflags libtracefs)
 
 CFLAGS :=      -O -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(MOPTS) $(WOPTS) $(TRACEFS_HEADERS) $(EXTRA_CFLAGS) -I include
-LDFLAGS        :=      -ggdb $(EXTRA_LDFLAGS)
+LDFLAGS        :=      -flto=auto -ggdb $(EXTRA_LDFLAGS)
 LIBS   :=      $$($(PKG_CONFIG) --libs libtracefs)
 
 SRC    :=      $(wildcard src/*.c)
index ad28582bcf2b1ca6b6c9ba9e5d09b0bb5fbe63c0..f04479ecc96c0b75af1afb2e7855cf1cf2491970 100644 (file)
@@ -210,9 +210,9 @@ static char *ikm_read_reactor(char *monitor_name)
 static char *ikm_get_current_reactor(char *monitor_name)
 {
        char *reactors = ikm_read_reactor(monitor_name);
+       char *curr_reactor = NULL;
        char *start;
        char *end;
-       char *curr_reactor;
 
        if (!reactors)
                return NULL;